All of lore.kernel.org
 help / color / mirror / Atom feed
* RFC Patch: Add signal strength to nl80211station info
@ 2008-11-25 20:31 Henning Rogge
  2008-11-25 20:47 ` Johannes Berg
  0 siblings, 1 reply; 66+ messages in thread
From: Henning Rogge @ 2008-11-25 20:31 UTC (permalink / raw)
  To: linux-wireless


[-- Attachment #1.1: Type: text/plain, Size: 3232 bytes --]

Hello,

I have just written a prototype of a patch that adds signal strength information to the nl80211 station info. This allows user space programs to keep track of the signal 
strength of each other station in communication range (in adhoc mode) without using radiotap headers (which consume lots of cpu power on embedded systems).

I have tested the patch with a modified iw command on ath5k. I'm still looking for a way to add the datarate of unicast for each of the stations in range, but would like 
to hear comments about the patch.

-------------------------------------------
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index e08c8bc..1e20e47 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -413,7 +413,10 @@ enum nl80211_sta_info {
 	NL80211_STA_INFO_LLID,
 	NL80211_STA_INFO_PLID,
 	NL80211_STA_INFO_PLINK_STATE,
-
+	NL80211_STA_INFO_SIGNAL,
+	NL80211_STA_INFO_NOISE,
+	NL80211_STA_INFO_QUAL,
+	
 	/* keep last */
 	__NL80211_STA_INFO_AFTER_LAST,
 	NL80211_STA_INFO_MAX = __NL80211_STA_INFO_AFTER_LAST - 1
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 1d57835..7fc1aaf 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -175,6 +175,9 @@ enum station_info_flags {
 	STATION_INFO_LLID		= 1<<3,
 	STATION_INFO_PLID		= 1<<4,
 	STATION_INFO_PLINK_STATE	= 1<<5,
+	STATION_INFO_SIGNAL		= 1<<6,
+	STATION_INFO_NOISE		= 1<<7,
+	STATION_INFO_QUAL		= 1<<8,
 };
 
 /**
@@ -195,6 +198,7 @@ struct station_info {
 	u32 inactive_time;
 	u32 rx_bytes;
 	u32 tx_bytes;
+	u32 signal,noise,qual;
 	u16 llid;
 	u16 plid;
 	u8 plink_state;
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 16423f9..8006555 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -310,12 +310,18 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
 
 	sinfo->filled = STATION_INFO_INACTIVE_TIME |
 			STATION_INFO_RX_BYTES |
-			STATION_INFO_TX_BYTES;
+			STATION_INFO_TX_BYTES |
+			STATION_INFO_SIGNAL |
+			STATION_INFO_NOISE |
+			STATION_INFO_QUAL;
 
 	sinfo->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx);
 	sinfo->rx_bytes = sta->rx_bytes;
 	sinfo->tx_bytes = sta->tx_bytes;
-
+	sinfo->signal = sta->last_signal;
+	sinfo->qual = sta->last_qual;
+	sinfo->noise = sta->last_noise;
+	
 	if (ieee80211_vif_is_mesh(&sdata->vif)) {
 #ifdef CONFIG_MAC80211_MESH
 		sinfo->filled |= STATION_INFO_LLID |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index c9141e3..de30b1a 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -1057,6 +1057,15 @@ static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
 	if (sinfo->filled & STATION_INFO_PLINK_STATE)
 		NLA_PUT_U8(msg, NL80211_STA_INFO_PLINK_STATE,
 			    sinfo->plink_state);
+	if (sinfo->filled & STATION_INFO_SIGNAL)
+		NLA_PUT_U32(msg, NL80211_STA_INFO_SIGNAL,
+			    sinfo->signal);
+	if (sinfo->filled & STATION_INFO_NOISE)
+		NLA_PUT_U32(msg, NL80211_STA_INFO_NOISE,
+			    sinfo->noise);
+	if (sinfo->filled & STATION_INFO_QUAL)
+		NLA_PUT_U32(msg, NL80211_STA_INFO_QUAL,
+			    sinfo->qual);
 
 	nla_nest_end(msg, sinfoattr);
 


[-- Attachment #1.2: wireless.patch --]
[-- Type: text/x-patch, Size: 2635 bytes --]

diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index e08c8bc..1e20e47 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -413,7 +413,10 @@ enum nl80211_sta_info {
 	NL80211_STA_INFO_LLID,
 	NL80211_STA_INFO_PLID,
 	NL80211_STA_INFO_PLINK_STATE,
-
+	NL80211_STA_INFO_SIGNAL,
+	NL80211_STA_INFO_NOISE,
+	NL80211_STA_INFO_QUAL,
+	
 	/* keep last */
 	__NL80211_STA_INFO_AFTER_LAST,
 	NL80211_STA_INFO_MAX = __NL80211_STA_INFO_AFTER_LAST - 1
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 1d57835..7fc1aaf 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -175,6 +175,9 @@ enum station_info_flags {
 	STATION_INFO_LLID		= 1<<3,
 	STATION_INFO_PLID		= 1<<4,
 	STATION_INFO_PLINK_STATE	= 1<<5,
+	STATION_INFO_SIGNAL		= 1<<6,
+	STATION_INFO_NOISE		= 1<<7,
+	STATION_INFO_QUAL		= 1<<8,
 };
 
 /**
@@ -195,6 +198,7 @@ struct station_info {
 	u32 inactive_time;
 	u32 rx_bytes;
 	u32 tx_bytes;
+	u32 signal,noise,qual;
 	u16 llid;
 	u16 plid;
 	u8 plink_state;
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 16423f9..8006555 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -310,12 +310,18 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
 
 	sinfo->filled = STATION_INFO_INACTIVE_TIME |
 			STATION_INFO_RX_BYTES |
-			STATION_INFO_TX_BYTES;
+			STATION_INFO_TX_BYTES |
+			STATION_INFO_SIGNAL |
+			STATION_INFO_NOISE |
+			STATION_INFO_QUAL;
 
 	sinfo->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx);
 	sinfo->rx_bytes = sta->rx_bytes;
 	sinfo->tx_bytes = sta->tx_bytes;
-
+	sinfo->signal = sta->last_signal;
+	sinfo->qual = sta->last_qual;
+	sinfo->noise = sta->last_noise;
+	
 	if (ieee80211_vif_is_mesh(&sdata->vif)) {
 #ifdef CONFIG_MAC80211_MESH
 		sinfo->filled |= STATION_INFO_LLID |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index c9141e3..de30b1a 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -1057,6 +1057,15 @@ static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
 	if (sinfo->filled & STATION_INFO_PLINK_STATE)
 		NLA_PUT_U8(msg, NL80211_STA_INFO_PLINK_STATE,
 			    sinfo->plink_state);
+	if (sinfo->filled & STATION_INFO_SIGNAL)
+		NLA_PUT_U32(msg, NL80211_STA_INFO_SIGNAL,
+			    sinfo->signal);
+	if (sinfo->filled & STATION_INFO_NOISE)
+		NLA_PUT_U32(msg, NL80211_STA_INFO_NOISE,
+			    sinfo->noise);
+	if (sinfo->filled & STATION_INFO_QUAL)
+		NLA_PUT_U32(msg, NL80211_STA_INFO_QUAL,
+			    sinfo->qual);
 
 	nla_nest_end(msg, sinfoattr);
 

[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 197 bytes --]

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

* Re: RFC Patch: Add signal strength to nl80211station info
  2008-11-25 20:31 RFC Patch: Add signal strength to nl80211station info Henning Rogge
@ 2008-11-25 20:47 ` Johannes Berg
  2008-11-25 21:01   ` Henning Rogge
  2008-11-26  5:21   ` Marcel Holtmann
  0 siblings, 2 replies; 66+ messages in thread
From: Johannes Berg @ 2008-11-25 20:47 UTC (permalink / raw)
  To: Henning Rogge; +Cc: linux-wireless

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

On Tue, 2008-11-25 at 21:31 +0100, Henning Rogge wrote:


> +	NL80211_STA_INFO_SIGNAL,
> +	NL80211_STA_INFO_NOISE,
> +	NL80211_STA_INFO_QUAL,

Sorry, no, this WEXT junk is just too undefined to put it into nl80211.

johannes

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

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

* Re: RFC Patch: Add signal strength to nl80211station info
  2008-11-25 20:47 ` Johannes Berg
@ 2008-11-25 21:01   ` Henning Rogge
  2008-11-26  5:21   ` Marcel Holtmann
  1 sibling, 0 replies; 66+ messages in thread
From: Henning Rogge @ 2008-11-25 21:01 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linux-wireless

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

On Tuesday 25 November 2008 21:47:17 Johannes Berg wrote:
> On Tue, 2008-11-25 at 21:31 +0100, Henning Rogge wrote:
> > +	NL80211_STA_INFO_SIGNAL,
> > +	NL80211_STA_INFO_NOISE,
> > +	NL80211_STA_INFO_QUAL,
>
> Sorry, no, this WEXT junk is just too undefined to put it into nl80211.
It was an experiment... the question is, what kind of information about signal 
strength or SNR would be good enough to make it available to userspace.

At the moment there is no way to get this information without a huge overhead 
of cpu power (raw sockets + monitor mode + radiotap)

Henning

[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 197 bytes --]

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

* Re: RFC Patch: Add signal strength to nl80211station info
  2008-11-25 20:47 ` Johannes Berg
  2008-11-25 21:01   ` Henning Rogge
@ 2008-11-26  5:21   ` Marcel Holtmann
  2008-11-26  8:32     ` Johannes Berg
                       ` (2 more replies)
  1 sibling, 3 replies; 66+ messages in thread
From: Marcel Holtmann @ 2008-11-26  5:21 UTC (permalink / raw)
  To: Johannes Berg; +Cc: Henning Rogge, linux-wireless

Hi Johannes,

>> +	NL80211_STA_INFO_SIGNAL,
>> +	NL80211_STA_INFO_NOISE,
>> +	NL80211_STA_INFO_QUAL,
>
> Sorry, no, this WEXT junk is just too undefined to put it into  
> nl80211.

I know that WEXT were pretty bad in describing what to expect from  
these values and every driver did whatever it thought it would be  
best. Can we not just try to define how these values should be filled  
in and then either mark drivers as broken or try to fix them? Just an  
idea.

Regards

Marcel


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

* Re: RFC Patch: Add signal strength to nl80211station info
  2008-11-26  5:21   ` Marcel Holtmann
@ 2008-11-26  8:32     ` Johannes Berg
  2008-11-26 16:17     ` Henning Rogge
  2008-11-29 10:50     ` RFC Patch v2: " Henning Rogge
  2 siblings, 0 replies; 66+ messages in thread
From: Johannes Berg @ 2008-11-26  8:32 UTC (permalink / raw)
  To: Marcel Holtmann; +Cc: Henning Rogge, linux-wireless

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

On Wed, 2008-11-26 at 06:21 +0100, Marcel Holtmann wrote:
> Hi Johannes,
> 
> >> +	NL80211_STA_INFO_SIGNAL,
> >> +	NL80211_STA_INFO_NOISE,
> >> +	NL80211_STA_INFO_QUAL,
> >
> > Sorry, no, this WEXT junk is just too undefined to put it into  
> > nl80211.
> 
> I know that WEXT were pretty bad in describing what to expect from  
> these values and every driver did whatever it thought it would be  
> best. Can we not just try to define how these values should be filled  
> in and then either mark drivers as broken or try to fix them? Just an  
> idea.

But it doesn't even physically make sense. The noise is not per station
but rather per channel, if you know it at all. The "quality" is simply
not defined, and would usually be "signal", unless you're doing
something else to estimate "quality", like taking into account
retransmissions, ... And then signal/noise should be in dBm.

johannes

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

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

* Re: RFC Patch: Add signal strength to nl80211station info
  2008-11-26  5:21   ` Marcel Holtmann
  2008-11-26  8:32     ` Johannes Berg
@ 2008-11-26 16:17     ` Henning Rogge
  2008-11-29 10:50     ` RFC Patch v2: " Henning Rogge
  2 siblings, 0 replies; 66+ messages in thread
From: Henning Rogge @ 2008-11-26 16:17 UTC (permalink / raw)
  To: Marcel Holtmann; +Cc: Johannes Berg, linux-wireless

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

On Wednesday 26 November 2008 06:21:40 Marcel Holtmann wrote:
> Hi Johannes,
>
> >> +	NL80211_STA_INFO_SIGNAL,
> >> +	NL80211_STA_INFO_NOISE,
> >> +	NL80211_STA_INFO_QUAL,
> >
> > Sorry, no, this WEXT junk is just too undefined to put it into
> > nl80211.
>
> I know that WEXT were pretty bad in describing what to expect from
> these values and every driver did whatever it thought it would be
> best. Can we not just try to define how these values should be filled
> in and then either mark drivers as broken or try to fix them? Just an
> idea.
That would be a great thing... it's not that I really need the noise level (or 
the quality value), I was just testing how easy I can push values through 
nl80211 into userspace. The layer 1/2 data I'm looking for is signalstrength 
and transmission rate for each adhoc communication partner. And I still think 
the mac80211 stack is missing some easy way to get them at the moment.

Henning

[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 197 bytes --]

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

* Re: RFC Patch v2: Add signal strength to nl80211station info
  2008-11-26  5:21   ` Marcel Holtmann
  2008-11-26  8:32     ` Johannes Berg
  2008-11-26 16:17     ` Henning Rogge
@ 2008-11-29 10:50     ` Henning Rogge
  2008-12-01 11:17       ` Johannes Berg
  2 siblings, 1 reply; 66+ messages in thread
From: Henning Rogge @ 2008-11-29 10:50 UTC (permalink / raw)
  To: Marcel Holtmann; +Cc: Johannes Berg, linux-wireless


[-- Attachment #1.1: Type: text/plain, Size: 3502 bytes --]

On Wednesday 26 November 2008 06:21:40 Marcel Holtmann wrote:
> I know that WEXT were pretty bad in describing what to expect from
> these values and every driver did whatever it thought it would be
> best. Can we not just try to define how these values should be filled
> in and then either mark drivers as broken or try to fix them? Just an
> idea.

I just created a second patch for station info.

Changes since v1:
- removed noise and quality from station info in NL80211
- added bandwith to station info in NL80211
- changed name of patch file to nl80211ext_v2.patch

The problem of a well defined signal strength value is still not addressed, 
but I have not enough knowledge about the driver specific implementations to 
make a good suggestion I think.

Henning

---------------------------------------------------

diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index e08c8bc..a9639fa 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -413,6 +413,8 @@ enum nl80211_sta_info {
 	NL80211_STA_INFO_LLID,
 	NL80211_STA_INFO_PLID,
 	NL80211_STA_INFO_PLINK_STATE,
+	NL80211_STA_INFO_SIGNAL,
+	NL80211_STA_INFO_BANDWITH,
 
 	/* keep last */
 	__NL80211_STA_INFO_AFTER_LAST,
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 1d57835..3621ae2 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -175,6 +175,8 @@ enum station_info_flags {
 	STATION_INFO_LLID		= 1<<3,
 	STATION_INFO_PLID		= 1<<4,
 	STATION_INFO_PLINK_STATE	= 1<<5,
+	STATION_INFO_SIGNAL		= 1<<6,
+	STATION_INFO_BANDWITH		= 1<<7,
 };
 
 /**
@@ -198,6 +200,8 @@ struct station_info {
 	u16 llid;
 	u16 plid;
 	u8 plink_state;
+	u8 signal;
+	u16 bandwith;
 };
 
 /**
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 16423f9..14e3457 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -307,14 +307,24 @@ static int ieee80211_config_default_key(struct wiphy 
*wiphy,
 static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
 {
 	struct ieee80211_sub_if_data *sdata = sta->sdata;
+  struct ieee80211_supported_band *sband;
 
 	sinfo->filled = STATION_INFO_INACTIVE_TIME |
 			STATION_INFO_RX_BYTES |
-			STATION_INFO_TX_BYTES;
+			STATION_INFO_TX_BYTES |
+			STATION_INFO_SIGNAL |
+			STATION_INFO_BANDWITH;
 
 	sinfo->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx);
 	sinfo->rx_bytes = sta->rx_bytes;
 	sinfo->tx_bytes = sta->tx_bytes;
+	sinfo->signal = sta->last_signal;
+
+	sband = sta->local->hw.wiphy->bands[sta->local->hw.conf.channel->band];
+	if (!(sta->last_tx_rate.flags & IEEE80211_TX_RC_MCS))
+	  sinfo->bandwith = sband->bitrates[sta->last_tx_rate.idx].bitrate;
+	else
+	  sinfo->bandwith = 0;
 
 	if (ieee80211_vif_is_mesh(&sdata->vif)) {
 #ifdef CONFIG_MAC80211_MESH
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index c9141e3..225ec26 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -1057,6 +1057,12 @@ static int nl80211_send_station(struct sk_buff *msg, 
u32 pid, u32 seq,
 	if (sinfo->filled & STATION_INFO_PLINK_STATE)
 		NLA_PUT_U8(msg, NL80211_STA_INFO_PLINK_STATE,
 			    sinfo->plink_state);
+	if (sinfo->filled & STATION_INFO_SIGNAL)
+		NLA_PUT_U8(msg, NL80211_STA_INFO_SIGNAL,
+			    sinfo->signal);
+	if (sinfo->filled & STATION_INFO_BANDWITH)
+		NLA_PUT_U16(msg, NL80211_STA_INFO_BANDWITH,
+			    sinfo->bandwith);
 
 	nla_nest_end(msg, sinfoattr);
 


[-- Attachment #1.2: nl80211ext_v2.patch --]
[-- Type: text/x-patch, Size: 2651 bytes --]

diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index e08c8bc..a9639fa 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -413,6 +413,8 @@ enum nl80211_sta_info {
 	NL80211_STA_INFO_LLID,
 	NL80211_STA_INFO_PLID,
 	NL80211_STA_INFO_PLINK_STATE,
+	NL80211_STA_INFO_SIGNAL,
+	NL80211_STA_INFO_BANDWITH,
 
 	/* keep last */
 	__NL80211_STA_INFO_AFTER_LAST,
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 1d57835..3621ae2 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -175,6 +175,8 @@ enum station_info_flags {
 	STATION_INFO_LLID		= 1<<3,
 	STATION_INFO_PLID		= 1<<4,
 	STATION_INFO_PLINK_STATE	= 1<<5,
+	STATION_INFO_SIGNAL		= 1<<6,
+	STATION_INFO_BANDWITH		= 1<<7,
 };
 
 /**
@@ -198,6 +200,8 @@ struct station_info {
 	u16 llid;
 	u16 plid;
 	u8 plink_state;
+	u8 signal;
+	u16 bandwith;
 };
 
 /**
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 16423f9..14e3457 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -307,14 +307,24 @@ static int ieee80211_config_default_key(struct wiphy *wiphy,
 static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
 {
 	struct ieee80211_sub_if_data *sdata = sta->sdata;
+  struct ieee80211_supported_band *sband;
 
 	sinfo->filled = STATION_INFO_INACTIVE_TIME |
 			STATION_INFO_RX_BYTES |
-			STATION_INFO_TX_BYTES;
+			STATION_INFO_TX_BYTES |
+			STATION_INFO_SIGNAL |
+			STATION_INFO_BANDWITH;
 
 	sinfo->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx);
 	sinfo->rx_bytes = sta->rx_bytes;
 	sinfo->tx_bytes = sta->tx_bytes;
+	sinfo->signal = sta->last_signal;
+
+	sband = sta->local->hw.wiphy->bands[sta->local->hw.conf.channel->band];
+	if (!(sta->last_tx_rate.flags & IEEE80211_TX_RC_MCS))
+	  sinfo->bandwith = sband->bitrates[sta->last_tx_rate.idx].bitrate;
+	else
+	  sinfo->bandwith = 0;
 
 	if (ieee80211_vif_is_mesh(&sdata->vif)) {
 #ifdef CONFIG_MAC80211_MESH
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index c9141e3..225ec26 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -1057,6 +1057,12 @@ static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
 	if (sinfo->filled & STATION_INFO_PLINK_STATE)
 		NLA_PUT_U8(msg, NL80211_STA_INFO_PLINK_STATE,
 			    sinfo->plink_state);
+	if (sinfo->filled & STATION_INFO_SIGNAL)
+		NLA_PUT_U8(msg, NL80211_STA_INFO_SIGNAL,
+			    sinfo->signal);
+	if (sinfo->filled & STATION_INFO_BANDWITH)
+		NLA_PUT_U16(msg, NL80211_STA_INFO_BANDWITH,
+			    sinfo->bandwith);
 
 	nla_nest_end(msg, sinfoattr);
 

[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 197 bytes --]

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

* Re: RFC Patch v2: Add signal strength to nl80211station info
  2008-11-29 10:50     ` RFC Patch v2: " Henning Rogge
@ 2008-12-01 11:17       ` Johannes Berg
  2008-12-01 13:22         ` Henning Rogge
  0 siblings, 1 reply; 66+ messages in thread
From: Johannes Berg @ 2008-12-01 11:17 UTC (permalink / raw)
  To: Henning Rogge; +Cc: Marcel Holtmann, linux-wireless

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

On Sat, 2008-11-29 at 11:50 +0100, Henning Rogge wrote:

> diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
> index e08c8bc..a9639fa 100644
> --- a/include/linux/nl80211.h
> +++ b/include/linux/nl80211.h
> @@ -413,6 +413,8 @@ enum nl80211_sta_info {
>  	NL80211_STA_INFO_LLID,
>  	NL80211_STA_INFO_PLID,
>  	NL80211_STA_INFO_PLINK_STATE,
> +	NL80211_STA_INFO_SIGNAL,
> +	NL80211_STA_INFO_BANDWITH,

Even if you corrected the spelling to "bandwidth" you'd (a) be missing
documentation and (b) be using an entirely wrong term for what you're
doing.

johannes

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

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

* Re: RFC Patch v2: Add signal strength to nl80211station info
  2008-12-01 11:17       ` Johannes Berg
@ 2008-12-01 13:22         ` Henning Rogge
  2008-12-01 17:39           ` Luis R. Rodriguez
  0 siblings, 1 reply; 66+ messages in thread
From: Henning Rogge @ 2008-12-01 13:22 UTC (permalink / raw)
  To: Johannes Berg; +Cc: Henning Rogge, Marcel Holtmann, linux-wireless


[-- Attachment #1.1: Type: text/plain, Size: 4893 bytes --]

Am Monday 01 December 2008 12:17:36 schrieb Johannes Berg:
> Even if you corrected the spelling to "bandwidth" you'd (a) be missing
> documentation and (b) be using an entirely wrong term for what you're
> doing.

Changes since v1:
- removed noise and quality from station info in NL80211
- added bandwith to station info in NL80211
- changed name of patch file to nl80211ext_v2.patch

Changes since v2:
- added kernel comment lines for new fields/enums
- changed name of "bandwith" field to tx_bitrate

Henning Rogge

*************************************************
Diplom Informatiker Henning Rogge
Forschungsgesellschaft für
Angewandte Naturwissenschaften e. V. (FGAN) 
Neuenahrer Str. 20, 53343 Wachtberg, Germany
Tel.: 0049 (0)228 9435-961
Fax: 0049 (0)228 9435-685
E-Mail: rogge@fgan.de
Web: www.fgan.de
************************************************
Sitz der Gesellschaft: Bonn
Registergericht: Amtsgericht Bonn VR 2530
Vorstand: Dr. rer. nat. Ralf Dornhaus (Vors.), Prof. Dr. Joachim Ender 
(Stellv.)

---------------------------------------------------

diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index e08c8bc..030feed 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -404,6 +404,8 @@ enum nl80211_sta_flags {
  * @NL80211_STA_INFO_TX_BYTES: total transmitted bytes (u32, to this station)
  * @__NL80211_STA_INFO_AFTER_LAST: internal
  * @NL80211_STA_INFO_MAX: highest possible station info attribute
+ * @NL80211_STA_INFO_SIGNAL: signal strength of last received package (u8, 
dBm)
+ * @NL80211_STA_INFO_TX_BITRATE: current unicast tx rate (u16, 100 kbit/s)
  */
 enum nl80211_sta_info {
 	__NL80211_STA_INFO_INVALID,
@@ -413,6 +415,8 @@ enum nl80211_sta_info {
 	NL80211_STA_INFO_LLID,
 	NL80211_STA_INFO_PLID,
 	NL80211_STA_INFO_PLINK_STATE,
+	NL80211_STA_INFO_SIGNAL,
+	NL80211_STA_INFO_TX_BITRATE,
 
 	/* keep last */
 	__NL80211_STA_INFO_AFTER_LAST,
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 1d57835..fd9964c 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -167,6 +167,8 @@ struct station_parameters {
  * @STATION_INFO_LLID: @llid filled
  * @STATION_INFO_PLID: @plid filled
  * @STATION_INFO_PLINK_STATE: @plink_state filled
+ * @STATION_INFO_SIGNAL: @signal filled
+ * @STATION_INFO_TX_BITRATE: @tx_bitrate filled
  */
 enum station_info_flags {
 	STATION_INFO_INACTIVE_TIME	= 1<<0,
@@ -175,6 +177,8 @@ enum station_info_flags {
 	STATION_INFO_LLID		= 1<<3,
 	STATION_INFO_PLID		= 1<<4,
 	STATION_INFO_PLINK_STATE	= 1<<5,
+	STATION_INFO_SIGNAL		= 1<<6,
+	STATION_INFO_TX_BITRATE		= 1<<7,
 };
 
 /**
@@ -189,6 +193,8 @@ enum station_info_flags {
  * @llid: mesh local link id
  * @plid: mesh peer link id
  * @plink_state: mesh peer link state
+ * @signal: signal strength of last received package in dBm
+ * @tx_bitrate: current unicast tx rate in 100 kbit/sec
  */
 struct station_info {
 	u32 filled;
@@ -198,6 +204,8 @@ struct station_info {
 	u16 llid;
 	u16 plid;
 	u8 plink_state;
+	u8 signal;
+	u16 tx_bitrate;
 };
 
 /**
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 16423f9..f6ed5b5 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -307,14 +307,24 @@ static int ieee80211_config_default_key(struct wiphy 
*wiphy,
 static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
 {
 	struct ieee80211_sub_if_data *sdata = sta->sdata;
+  struct ieee80211_supported_band *sband;
 
 	sinfo->filled = STATION_INFO_INACTIVE_TIME |
 			STATION_INFO_RX_BYTES |
-			STATION_INFO_TX_BYTES;
+			STATION_INFO_TX_BYTES |
+			STATION_INFO_SIGNAL |
+			STATION_INFO_TX_BITRATE;
 
 	sinfo->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx);
 	sinfo->rx_bytes = sta->rx_bytes;
 	sinfo->tx_bytes = sta->tx_bytes;
+	sinfo->signal = sta->last_signal;
+
+	sband = sta->local->hw.wiphy->bands[sta->local->hw.conf.channel->band];
+	if (!(sta->last_tx_rate.flags & IEEE80211_TX_RC_MCS))
+	  sinfo->tx_bitrate = sband->bitrates[sta->last_tx_rate.idx].bitrate;
+	else
+	  sinfo->tx_bitrate = 0;
 
 	if (ieee80211_vif_is_mesh(&sdata->vif)) {
 #ifdef CONFIG_MAC80211_MESH
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index c9141e3..0afc641 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -1057,6 +1057,12 @@ static int nl80211_send_station(struct sk_buff *msg, 
u32 pid, u32 seq,
 	if (sinfo->filled & STATION_INFO_PLINK_STATE)
 		NLA_PUT_U8(msg, NL80211_STA_INFO_PLINK_STATE,
 			    sinfo->plink_state);
+	if (sinfo->filled & STATION_INFO_SIGNAL)
+		NLA_PUT_U8(msg, NL80211_STA_INFO_SIGNAL,
+			    sinfo->signal);
+	if (sinfo->filled & STATION_INFO_TX_BITRATE)
+		NLA_PUT_U16(msg, NL80211_STA_INFO_TX_BITRATE,
+			    sinfo->tx_bitrate);
 
 	nla_nest_end(msg, sinfoattr);
 


[-- Attachment #1.2: nl80211ext_v3.patch --]
[-- Type: text/x-patch, Size: 3785 bytes --]

diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index e08c8bc..030feed 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -404,6 +404,8 @@ enum nl80211_sta_flags {
  * @NL80211_STA_INFO_TX_BYTES: total transmitted bytes (u32, to this station)
  * @__NL80211_STA_INFO_AFTER_LAST: internal
  * @NL80211_STA_INFO_MAX: highest possible station info attribute
+ * @NL80211_STA_INFO_SIGNAL: signal strength of last received package (u8, dBm)
+ * @NL80211_STA_INFO_TX_BITRATE: current unicast tx rate (u16, 100 kbit/s)
  */
 enum nl80211_sta_info {
 	__NL80211_STA_INFO_INVALID,
@@ -413,6 +415,8 @@ enum nl80211_sta_info {
 	NL80211_STA_INFO_LLID,
 	NL80211_STA_INFO_PLID,
 	NL80211_STA_INFO_PLINK_STATE,
+	NL80211_STA_INFO_SIGNAL,
+	NL80211_STA_INFO_TX_BITRATE,
 
 	/* keep last */
 	__NL80211_STA_INFO_AFTER_LAST,
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 1d57835..fd9964c 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -167,6 +167,8 @@ struct station_parameters {
  * @STATION_INFO_LLID: @llid filled
  * @STATION_INFO_PLID: @plid filled
  * @STATION_INFO_PLINK_STATE: @plink_state filled
+ * @STATION_INFO_SIGNAL: @signal filled
+ * @STATION_INFO_TX_BITRATE: @tx_bitrate filled
  */
 enum station_info_flags {
 	STATION_INFO_INACTIVE_TIME	= 1<<0,
@@ -175,6 +177,8 @@ enum station_info_flags {
 	STATION_INFO_LLID		= 1<<3,
 	STATION_INFO_PLID		= 1<<4,
 	STATION_INFO_PLINK_STATE	= 1<<5,
+	STATION_INFO_SIGNAL		= 1<<6,
+	STATION_INFO_TX_BITRATE		= 1<<7,
 };
 
 /**
@@ -189,6 +193,8 @@ enum station_info_flags {
  * @llid: mesh local link id
  * @plid: mesh peer link id
  * @plink_state: mesh peer link state
+ * @signal: signal strength of last received package in dBm
+ * @tx_bitrate: current unicast tx rate in 100 kbit/sec
  */
 struct station_info {
 	u32 filled;
@@ -198,6 +204,8 @@ struct station_info {
 	u16 llid;
 	u16 plid;
 	u8 plink_state;
+	u8 signal;
+	u16 tx_bitrate;
 };
 
 /**
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 16423f9..f6ed5b5 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -307,14 +307,24 @@ static int ieee80211_config_default_key(struct wiphy *wiphy,
 static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
 {
 	struct ieee80211_sub_if_data *sdata = sta->sdata;
+  struct ieee80211_supported_band *sband;
 
 	sinfo->filled = STATION_INFO_INACTIVE_TIME |
 			STATION_INFO_RX_BYTES |
-			STATION_INFO_TX_BYTES;
+			STATION_INFO_TX_BYTES |
+			STATION_INFO_SIGNAL |
+			STATION_INFO_TX_BITRATE;
 
 	sinfo->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx);
 	sinfo->rx_bytes = sta->rx_bytes;
 	sinfo->tx_bytes = sta->tx_bytes;
+	sinfo->signal = sta->last_signal;
+
+	sband = sta->local->hw.wiphy->bands[sta->local->hw.conf.channel->band];
+	if (!(sta->last_tx_rate.flags & IEEE80211_TX_RC_MCS))
+	  sinfo->tx_bitrate = sband->bitrates[sta->last_tx_rate.idx].bitrate;
+	else
+	  sinfo->tx_bitrate = 0;
 
 	if (ieee80211_vif_is_mesh(&sdata->vif)) {
 #ifdef CONFIG_MAC80211_MESH
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index c9141e3..0afc641 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -1057,6 +1057,12 @@ static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
 	if (sinfo->filled & STATION_INFO_PLINK_STATE)
 		NLA_PUT_U8(msg, NL80211_STA_INFO_PLINK_STATE,
 			    sinfo->plink_state);
+	if (sinfo->filled & STATION_INFO_SIGNAL)
+		NLA_PUT_U8(msg, NL80211_STA_INFO_SIGNAL,
+			    sinfo->signal);
+	if (sinfo->filled & STATION_INFO_TX_BITRATE)
+		NLA_PUT_U16(msg, NL80211_STA_INFO_TX_BITRATE,
+			    sinfo->tx_bitrate);
 
 	nla_nest_end(msg, sinfoattr);
 

[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 197 bytes --]

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

* Re: RFC Patch v2: Add signal strength to nl80211station info
  2008-12-01 13:22         ` Henning Rogge
@ 2008-12-01 17:39           ` Luis R. Rodriguez
  2008-12-01 17:45             ` Luis R. Rodriguez
                               ` (2 more replies)
  0 siblings, 3 replies; 66+ messages in thread
From: Luis R. Rodriguez @ 2008-12-01 17:39 UTC (permalink / raw)
  To: Henning Rogge
  Cc: Johannes Berg, Henning Rogge, Marcel Holtmann, linux-wireless, nbd

On Mon, Dec 01, 2008 at 05:22:23AM -0800, Henning Rogge wrote:
> Am Monday 01 December 2008 12:17:36 schrieb Johannes Berg:
> > Even if you corrected the spelling to "bandwidth" you'd (a) be miss=
ing
> > documentation and (b) be using an entirely wrong term for what you'=
re
> > doing.
>=20
> Changes since v1:
> - removed noise and quality from station info in NL80211
> - added bandwith to station info in NL80211
> - changed name of patch file to nl80211ext_v2.patch
>=20
> Changes since v2:
> - added kernel comment lines for new fields/enums
> - changed name of "bandwith" field to tx_bitrate
>=20
> Henning Rogge
>=20
> *************************************************
> Diplom Informatiker Henning Rogge
> Forschungsgesellschaft f=FCr
> Angewandte Naturwissenschaften e. V. (FGAN)=20
> Neuenahrer Str. 20, 53343 Wachtberg, Germany
> Tel.: 0049 (0)228 9435-961
> Fax: 0049 (0)228 9435-685
> E-Mail: rogge@fgan.de
> Web: www.fgan.de
> ************************************************
> Sitz der Gesellschaft: Bonn
> Registergericht: Amtsgericht Bonn VR 2530
> Vorstand: Dr. rer. nat. Ralf Dornhaus (Vors.), Prof. Dr. Joachim Ende=
r=20
> (Stellv.)
>=20
> ---------------------------------------------------
>=20
> diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
> index e08c8bc..030feed 100644
> --- a/include/linux/nl80211.h
> +++ b/include/linux/nl80211.h
> @@ -404,6 +404,8 @@ enum nl80211_sta_flags {
>   * @NL80211_STA_INFO_TX_BYTES: total transmitted bytes (u32, to this=
 station)
>   * @__NL80211_STA_INFO_AFTER_LAST: internal
>   * @NL80211_STA_INFO_MAX: highest possible station info attribute
> + * @NL80211_STA_INFO_SIGNAL: signal strength of last received packag=
e (u8,=20
> dBm)
> + * @NL80211_STA_INFO_TX_BITRATE: current unicast tx rate (u16, 100 k=
bit/s)
>   */
>  enum nl80211_sta_info {
>  	__NL80211_STA_INFO_INVALID,
> @@ -413,6 +415,8 @@ enum nl80211_sta_info {
>  	NL80211_STA_INFO_LLID,
>  	NL80211_STA_INFO_PLID,
>  	NL80211_STA_INFO_PLINK_STATE,
> +	NL80211_STA_INFO_SIGNAL,
> +	NL80211_STA_INFO_TX_BITRATE,
> =20
>  	/* keep last */
>  	__NL80211_STA_INFO_AFTER_LAST,
> diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
> index 1d57835..fd9964c 100644
> --- a/include/net/cfg80211.h
> +++ b/include/net/cfg80211.h
> @@ -167,6 +167,8 @@ struct station_parameters {
>   * @STATION_INFO_LLID: @llid filled
>   * @STATION_INFO_PLID: @plid filled
>   * @STATION_INFO_PLINK_STATE: @plink_state filled
> + * @STATION_INFO_SIGNAL: @signal filled
> + * @STATION_INFO_TX_BITRATE: @tx_bitrate filled
>   */
>  enum station_info_flags {
>  	STATION_INFO_INACTIVE_TIME	=3D 1<<0,
> @@ -175,6 +177,8 @@ enum station_info_flags {
>  	STATION_INFO_LLID		=3D 1<<3,
>  	STATION_INFO_PLID		=3D 1<<4,
>  	STATION_INFO_PLINK_STATE	=3D 1<<5,
> +	STATION_INFO_SIGNAL		=3D 1<<6,
> +	STATION_INFO_TX_BITRATE		=3D 1<<7,
>  };
> =20
>  /**
> @@ -189,6 +193,8 @@ enum station_info_flags {
>   * @llid: mesh local link id
>   * @plid: mesh peer link id
>   * @plink_state: mesh peer link state
> + * @signal: signal strength of last received package in dBm
> + * @tx_bitrate: current unicast tx rate in 100 kbit/sec
>   */
>  struct station_info {
>  	u32 filled;
> @@ -198,6 +204,8 @@ struct station_info {
>  	u16 llid;
>  	u16 plid;
>  	u8 plink_state;
> +	u8 signal;
> +	u16 tx_bitrate;
>  };
> =20
>  /**
> diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
> index 16423f9..f6ed5b5 100644
> --- a/net/mac80211/cfg.c
> +++ b/net/mac80211/cfg.c
> @@ -307,14 +307,24 @@ static int ieee80211_config_default_key(struct =
wiphy=20
> *wiphy,
>  static void sta_set_sinfo(struct sta_info *sta, struct station_info =
*sinfo)
>  {
>  	struct ieee80211_sub_if_data *sdata =3D sta->sdata;
> +  struct ieee80211_supported_band *sband;
> =20
>  	sinfo->filled =3D STATION_INFO_INACTIVE_TIME |
>  			STATION_INFO_RX_BYTES |
> -			STATION_INFO_TX_BYTES;
> +			STATION_INFO_TX_BYTES |
> +			STATION_INFO_SIGNAL |
> +			STATION_INFO_TX_BITRATE;
> =20
>  	sinfo->inactive_time =3D jiffies_to_msecs(jiffies - sta->last_rx);
>  	sinfo->rx_bytes =3D sta->rx_bytes;
>  	sinfo->tx_bytes =3D sta->tx_bytes;
> +	sinfo->signal =3D sta->last_signal;
> +
> +	sband =3D sta->local->hw.wiphy->bands[sta->local->hw.conf.channel->=
band];
> +	if (!(sta->last_tx_rate.flags & IEEE80211_TX_RC_MCS))
> +	  sinfo->tx_bitrate =3D sband->bitrates[sta->last_tx_rate.idx].bitr=
ate;
> +	else
> +	  sinfo->tx_bitrate =3D 0;

It would be nice to get this figured out before adding it. We got rando=
m
complaints from users claiming 802.11n wasn't working before because
iwconfig didn't report a good rate. Users will trust it so I'd rather
see this go in with MCS rate figured out as part of the API to avoid
such reports. Would it be possible for you to work on that?

This might come in handy:

http://wireless.kernel.org/en/developers/Documentation/ieee80211/802.11=
n#MCSRates

What you need then is the guard interval, the MCS rate index and the
number of streams being used for communication.=20

  Luis
--
To unsubscribe from this list: send the line "unsubscribe linux-wireles=
s" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: RFC Patch v2: Add signal strength to nl80211station info
  2008-12-01 17:39           ` Luis R. Rodriguez
@ 2008-12-01 17:45             ` Luis R. Rodriguez
  2008-12-01 17:53             ` Henning Rogge
  2008-12-02 13:25             ` Henning Rogge
  2 siblings, 0 replies; 66+ messages in thread
From: Luis R. Rodriguez @ 2008-12-01 17:45 UTC (permalink / raw)
  To: Henning Rogge
  Cc: Johannes Berg, Henning Rogge, Marcel Holtmann, linux-wireless, nbd

T24gTW9uLCBEZWMgMSwgMjAwOCBhdCA5OjM5IEFNLCBMdWlzIFIuIFJvZHJpZ3Vlego8bHJvZHJp
Z3VlekBhdGhlcm9zLmNvbT4gd3JvdGU6Cj4gT24gTW9uLCBEZWMgMDEsIDIwMDggYXQgMDU6MjI6
MjNBTSAtMDgwMCwgSGVubmluZyBSb2dnZSB3cm90ZToKPj4gQW0gTW9uZGF5IDAxIERlY2VtYmVy
IDIwMDggMTI6MTc6MzYgc2NocmllYiBKb2hhbm5lcyBCZXJnOgo+PiA+IEV2ZW4gaWYgeW91IGNv
cnJlY3RlZCB0aGUgc3BlbGxpbmcgdG8gImJhbmR3aWR0aCIgeW91J2QgKGEpIGJlIG1pc3NpbmcK
Pj4gPiBkb2N1bWVudGF0aW9uIGFuZCAoYikgYmUgdXNpbmcgYW4gZW50aXJlbHkgd3JvbmcgdGVy
bSBmb3Igd2hhdCB5b3UncmUKPj4gPiBkb2luZy4KPj4KPj4gQ2hhbmdlcyBzaW5jZSB2MToKPj4g
LSByZW1vdmVkIG5vaXNlIGFuZCBxdWFsaXR5IGZyb20gc3RhdGlvbiBpbmZvIGluIE5MODAyMTEK
Pj4gLSBhZGRlZCBiYW5kd2l0aCB0byBzdGF0aW9uIGluZm8gaW4gTkw4MDIxMQo+PiAtIGNoYW5n
ZWQgbmFtZSBvZiBwYXRjaCBmaWxlIHRvIG5sODAyMTFleHRfdjIucGF0Y2gKPj4KPj4gQ2hhbmdl
cyBzaW5jZSB2MjoKPj4gLSBhZGRlZCBrZXJuZWwgY29tbWVudCBsaW5lcyBmb3IgbmV3IGZpZWxk
cy9lbnVtcwo+PiAtIGNoYW5nZWQgbmFtZSBvZiAiYmFuZHdpdGgiIGZpZWxkIHRvIHR4X2JpdHJh
dGUKPj4KPj4gSGVubmluZyBSb2dnZQo+Pgo+PiAqKioqKioqKioqKioqKioqKioqKioqKioqKioq
KioqKioqKioqKioqKioqKioqKioqCj4+IERpcGxvbSBJbmZvcm1hdGlrZXIgSGVubmluZyBSb2dn
ZQo+PiBGb3JzY2h1bmdzZ2VzZWxsc2NoYWZ0IGbDvHIKPj4gQW5nZXdhbmR0ZSBOYXR1cndpc3Nl
bnNjaGFmdGVuIGUuIFYuIChGR0FOKQo+PiBOZXVlbmFocmVyIFN0ci4gMjAsIDUzMzQzIFdhY2h0
YmVyZywgR2VybWFueQo+PiBUZWwuOiAwMDQ5ICgwKTIyOCA5NDM1LTk2MQo+PiBGYXg6IDAwNDkg
KDApMjI4IDk0MzUtNjg1Cj4+IEUtTWFpbDogcm9nZ2VAZmdhbi5kZQo+PiBXZWI6IHd3dy5mZ2Fu
LmRlCj4+ICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgo+
PiBTaXR6IGRlciBHZXNlbGxzY2hhZnQ6IEJvbm4KPj4gUmVnaXN0ZXJnZXJpY2h0OiBBbXRzZ2Vy
aWNodCBCb25uIFZSIDI1MzAKPj4gVm9yc3RhbmQ6IERyLiByZXIuIG5hdC4gUmFsZiBEb3JuaGF1
cyAoVm9ycy4pLCBQcm9mLiBEci4gSm9hY2hpbSBFbmRlcgo+PiAoU3RlbGx2LikKPj4KPj4gLS0t
LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCj4+Cj4+IGRp
ZmYgLS1naXQgYS9pbmNsdWRlL2xpbnV4L25sODAyMTEuaCBiL2luY2x1ZGUvbGludXgvbmw4MDIx
MS5oCj4+IGluZGV4IGUwOGM4YmMuLjAzMGZlZWQgMTAwNjQ0Cj4+IC0tLSBhL2luY2x1ZGUvbGlu
dXgvbmw4MDIxMS5oCj4+ICsrKyBiL2luY2x1ZGUvbGludXgvbmw4MDIxMS5oCj4+IEBAIC00MDQs
NiArNDA0LDggQEAgZW51bSBubDgwMjExX3N0YV9mbGFncyB7Cj4+ICAgKiBATkw4MDIxMV9TVEFf
SU5GT19UWF9CWVRFUzogdG90YWwgdHJhbnNtaXR0ZWQgYnl0ZXMgKHUzMiwgdG8gdGhpcyBzdGF0
aW9uKQo+PiAgICogQF9fTkw4MDIxMV9TVEFfSU5GT19BRlRFUl9MQVNUOiBpbnRlcm5hbAo+PiAg
ICogQE5MODAyMTFfU1RBX0lORk9fTUFYOiBoaWdoZXN0IHBvc3NpYmxlIHN0YXRpb24gaW5mbyBh
dHRyaWJ1dGUKPj4gKyAqIEBOTDgwMjExX1NUQV9JTkZPX1NJR05BTDogc2lnbmFsIHN0cmVuZ3Ro
IG9mIGxhc3QgcmVjZWl2ZWQgcGFja2FnZSAodTgsCj4+IGRCbSkKPj4gKyAqIEBOTDgwMjExX1NU
QV9JTkZPX1RYX0JJVFJBVEU6IGN1cnJlbnQgdW5pY2FzdCB0eCByYXRlICh1MTYsIDEwMCBrYml0
L3MpCj4+ICAgKi8KPj4gIGVudW0gbmw4MDIxMV9zdGFfaW5mbyB7Cj4+ICAgICAgIF9fTkw4MDIx
MV9TVEFfSU5GT19JTlZBTElELAo+PiBAQCAtNDEzLDYgKzQxNSw4IEBAIGVudW0gbmw4MDIxMV9z
dGFfaW5mbyB7Cj4+ICAgICAgIE5MODAyMTFfU1RBX0lORk9fTExJRCwKPj4gICAgICAgTkw4MDIx
MV9TVEFfSU5GT19QTElELAo+PiAgICAgICBOTDgwMjExX1NUQV9JTkZPX1BMSU5LX1NUQVRFLAo+
PiArICAgICBOTDgwMjExX1NUQV9JTkZPX1NJR05BTCwKPj4gKyAgICAgTkw4MDIxMV9TVEFfSU5G
T19UWF9CSVRSQVRFLAo+Pgo+PiAgICAgICAvKiBrZWVwIGxhc3QgKi8KPj4gICAgICAgX19OTDgw
MjExX1NUQV9JTkZPX0FGVEVSX0xBU1QsCj4+IGRpZmYgLS1naXQgYS9pbmNsdWRlL25ldC9jZmc4
MDIxMS5oIGIvaW5jbHVkZS9uZXQvY2ZnODAyMTEuaAo+PiBpbmRleCAxZDU3ODM1Li5mZDk5NjRj
IDEwMDY0NAo+PiAtLS0gYS9pbmNsdWRlL25ldC9jZmc4MDIxMS5oCj4+ICsrKyBiL2luY2x1ZGUv
bmV0L2NmZzgwMjExLmgKPj4gQEAgLTE2Nyw2ICsxNjcsOCBAQCBzdHJ1Y3Qgc3RhdGlvbl9wYXJh
bWV0ZXJzIHsKPj4gICAqIEBTVEFUSU9OX0lORk9fTExJRDogQGxsaWQgZmlsbGVkCj4+ICAgKiBA
U1RBVElPTl9JTkZPX1BMSUQ6IEBwbGlkIGZpbGxlZAo+PiAgICogQFNUQVRJT05fSU5GT19QTElO
S19TVEFURTogQHBsaW5rX3N0YXRlIGZpbGxlZAo+PiArICogQFNUQVRJT05fSU5GT19TSUdOQUw6
IEBzaWduYWwgZmlsbGVkCj4+ICsgKiBAU1RBVElPTl9JTkZPX1RYX0JJVFJBVEU6IEB0eF9iaXRy
YXRlIGZpbGxlZAo+PiAgICovCj4+ICBlbnVtIHN0YXRpb25faW5mb19mbGFncyB7Cj4+ICAgICAg
IFNUQVRJT05fSU5GT19JTkFDVElWRV9USU1FICAgICAgPSAxPDwwLAo+PiBAQCAtMTc1LDYgKzE3
Nyw4IEBAIGVudW0gc3RhdGlvbl9pbmZvX2ZsYWdzIHsKPj4gICAgICAgU1RBVElPTl9JTkZPX0xM
SUQgICAgICAgICAgICAgICA9IDE8PDMsCj4+ICAgICAgIFNUQVRJT05fSU5GT19QTElEICAgICAg
ICAgICAgICAgPSAxPDw0LAo+PiAgICAgICBTVEFUSU9OX0lORk9fUExJTktfU1RBVEUgICAgICAg
ID0gMTw8NSwKPj4gKyAgICAgU1RBVElPTl9JTkZPX1NJR05BTCAgICAgICAgICAgICA9IDE8PDYs
Cj4+ICsgICAgIFNUQVRJT05fSU5GT19UWF9CSVRSQVRFICAgICAgICAgPSAxPDw3LAo+PiAgfTsK
Pj4KPj4gIC8qKgo+PiBAQCAtMTg5LDYgKzE5Myw4IEBAIGVudW0gc3RhdGlvbl9pbmZvX2ZsYWdz
IHsKPj4gICAqIEBsbGlkOiBtZXNoIGxvY2FsIGxpbmsgaWQKPj4gICAqIEBwbGlkOiBtZXNoIHBl
ZXIgbGluayBpZAo+PiAgICogQHBsaW5rX3N0YXRlOiBtZXNoIHBlZXIgbGluayBzdGF0ZQo+PiAr
ICogQHNpZ25hbDogc2lnbmFsIHN0cmVuZ3RoIG9mIGxhc3QgcmVjZWl2ZWQgcGFja2FnZSBpbiBk
Qm0KPj4gKyAqIEB0eF9iaXRyYXRlOiBjdXJyZW50IHVuaWNhc3QgdHggcmF0ZSBpbiAxMDAga2Jp
dC9zZWMKPj4gICAqLwo+PiAgc3RydWN0IHN0YXRpb25faW5mbyB7Cj4+ICAgICAgIHUzMiBmaWxs
ZWQ7Cj4+IEBAIC0xOTgsNiArMjA0LDggQEAgc3RydWN0IHN0YXRpb25faW5mbyB7Cj4+ICAgICAg
IHUxNiBsbGlkOwo+PiAgICAgICB1MTYgcGxpZDsKPj4gICAgICAgdTggcGxpbmtfc3RhdGU7Cj4+
ICsgICAgIHU4IHNpZ25hbDsKPj4gKyAgICAgdTE2IHR4X2JpdHJhdGU7Cj4+ICB9Owo+Pgo+PiAg
LyoqCj4+IGRpZmYgLS1naXQgYS9uZXQvbWFjODAyMTEvY2ZnLmMgYi9uZXQvbWFjODAyMTEvY2Zn
LmMKPj4gaW5kZXggMTY0MjNmOS4uZjZlZDViNSAxMDA2NDQKPj4gLS0tIGEvbmV0L21hYzgwMjEx
L2NmZy5jCj4+ICsrKyBiL25ldC9tYWM4MDIxMS9jZmcuYwo+PiBAQCAtMzA3LDE0ICszMDcsMjQg
QEAgc3RhdGljIGludCBpZWVlODAyMTFfY29uZmlnX2RlZmF1bHRfa2V5KHN0cnVjdCB3aXBoeQo+
PiAqd2lwaHksCj4+ICBzdGF0aWMgdm9pZCBzdGFfc2V0X3NpbmZvKHN0cnVjdCBzdGFfaW5mbyAq
c3RhLCBzdHJ1Y3Qgc3RhdGlvbl9pbmZvICpzaW5mbykKPj4gIHsKPj4gICAgICAgc3RydWN0IGll
ZWU4MDIxMV9zdWJfaWZfZGF0YSAqc2RhdGEgPSBzdGEtPnNkYXRhOwo+PiArICBzdHJ1Y3QgaWVl
ZTgwMjExX3N1cHBvcnRlZF9iYW5kICpzYmFuZDsKPj4KPj4gICAgICAgc2luZm8tPmZpbGxlZCA9
IFNUQVRJT05fSU5GT19JTkFDVElWRV9USU1FIHwKPj4gICAgICAgICAgICAgICAgICAgICAgIFNU
QVRJT05fSU5GT19SWF9CWVRFUyB8Cj4+IC0gICAgICAgICAgICAgICAgICAgICBTVEFUSU9OX0lO
Rk9fVFhfQllURVM7Cj4+ICsgICAgICAgICAgICAgICAgICAgICBTVEFUSU9OX0lORk9fVFhfQllU
RVMgfAo+PiArICAgICAgICAgICAgICAgICAgICAgU1RBVElPTl9JTkZPX1NJR05BTCB8Cj4+ICsg
ICAgICAgICAgICAgICAgICAgICBTVEFUSU9OX0lORk9fVFhfQklUUkFURTsKPj4KPj4gICAgICAg
c2luZm8tPmluYWN0aXZlX3RpbWUgPSBqaWZmaWVzX3RvX21zZWNzKGppZmZpZXMgLSBzdGEtPmxh
c3RfcngpOwo+PiAgICAgICBzaW5mby0+cnhfYnl0ZXMgPSBzdGEtPnJ4X2J5dGVzOwo+PiAgICAg
ICBzaW5mby0+dHhfYnl0ZXMgPSBzdGEtPnR4X2J5dGVzOwo+PiArICAgICBzaW5mby0+c2lnbmFs
ID0gc3RhLT5sYXN0X3NpZ25hbDsKPj4gKwo+PiArICAgICBzYmFuZCA9IHN0YS0+bG9jYWwtPmh3
LndpcGh5LT5iYW5kc1tzdGEtPmxvY2FsLT5ody5jb25mLmNoYW5uZWwtPmJhbmRdOwo+PiArICAg
ICBpZiAoIShzdGEtPmxhc3RfdHhfcmF0ZS5mbGFncyAmIElFRUU4MDIxMV9UWF9SQ19NQ1MpKQo+
PiArICAgICAgIHNpbmZvLT50eF9iaXRyYXRlID0gc2JhbmQtPmJpdHJhdGVzW3N0YS0+bGFzdF90
eF9yYXRlLmlkeF0uYml0cmF0ZTsKPj4gKyAgICAgZWxzZQo+PiArICAgICAgIHNpbmZvLT50eF9i
aXRyYXRlID0gMDsKPgo+IEl0IHdvdWxkIGJlIG5pY2UgdG8gZ2V0IHRoaXMgZmlndXJlZCBvdXQg
YmVmb3JlIGFkZGluZyBpdC4gV2UgZ290IHJhbmRvbQo+IGNvbXBsYWludHMgZnJvbSB1c2VycyBj
bGFpbWluZyA4MDIuMTFuIHdhc24ndCB3b3JraW5nIGJlZm9yZSBiZWNhdXNlCj4gaXdjb25maWcg
ZGlkbid0IHJlcG9ydCBhIGdvb2QgcmF0ZS4gVXNlcnMgd2lsbCB0cnVzdCBpdCBzbyBJJ2QgcmF0
aGVyCj4gc2VlIHRoaXMgZ28gaW4gd2l0aCBNQ1MgcmF0ZSBmaWd1cmVkIG91dCBhcyBwYXJ0IG9m
IHRoZSBBUEkgdG8gYXZvaWQKPiBzdWNoIHJlcG9ydHMuIFdvdWxkIGl0IGJlIHBvc3NpYmxlIGZv
ciB5b3UgdG8gd29yayBvbiB0aGF0Pwo+Cj4gVGhpcyBtaWdodCBjb21lIGluIGhhbmR5Ogo+Cj4g
aHR0cDovL3dpcmVsZXNzLmtlcm5lbC5vcmcvZW4vZGV2ZWxvcGVycy9Eb2N1bWVudGF0aW9uL2ll
ZWU4MDIxMS84MDIuMTFuI01DU1JhdGVzCj4KPiBXaGF0IHlvdSBuZWVkIHRoZW4gaXMgdGhlIGd1
YXJkIGludGVydmFsLCB0aGUgTUNTIHJhdGUgaW5kZXggYW5kIHRoZQo+IG51bWJlciBvZiBzdHJl
YW1zIGJlaW5nIHVzZWQgZm9yIGNvbW11bmljYXRpb24uCgpBbHNvIGhvdyBhYm91dCB3ZSBhZGQg
YSBsYXN0IFRYIHJhdGUgYW5kIGxhc3QgUlggcmF0ZSBzbyB3ZSBnZXQgYm90aD8KCiBMdWlzCg==

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

* Re: RFC Patch v2: Add signal strength to nl80211station info
  2008-12-01 17:39           ` Luis R. Rodriguez
  2008-12-01 17:45             ` Luis R. Rodriguez
@ 2008-12-01 17:53             ` Henning Rogge
  2008-12-02 13:25             ` Henning Rogge
  2 siblings, 0 replies; 66+ messages in thread
From: Henning Rogge @ 2008-12-01 17:53 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: Henning Rogge, Johannes Berg, Marcel Holtmann, linux-wireless, nbd

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

On Monday 01 December 2008 18:39:48 Luis R. Rodriguez wrote:
> It would be nice to get this figured out before adding it. We got random
> complaints from users claiming 802.11n wasn't working before because
> iwconfig didn't report a good rate. Users will trust it so I'd rather
> see this go in with MCS rate figured out as part of the API to avoid
> such reports. Would it be possible for you to work on that?

> This might come in handy:
>
> http://wireless.kernel.org/en/developers/Documentation/ieee80211/802.11n#MC
>SRates
I will look at it... thank you for the link.

> What you need then is the guard interval, the MCS rate index and the
> number of streams being used for communication.

> Also how about we add a last TX rate and last RX rate so we get both?
Sounds like a good idea... have to look at the code of mac80211 a little bit 
more (I just copied the TX-rate thing from the wext code), but I really like 
the idea.

Henning

[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 197 bytes --]

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

* RFC Patch v2: Add signal strength to nl80211station info
  2008-12-01 17:39           ` Luis R. Rodriguez
  2008-12-01 17:45             ` Luis R. Rodriguez
  2008-12-01 17:53             ` Henning Rogge
@ 2008-12-02 13:25             ` Henning Rogge
  2008-12-02 20:29               ` Luis R. Rodriguez
  2 siblings, 1 reply; 66+ messages in thread
From: Henning Rogge @ 2008-12-02 13:25 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: Johannes Berg, Henning Rogge, Marcel Holtmann, linux-wireless, nbd


[-- Attachment #1.1: Type: text/plain, Size: 10795 bytes --]

Am Monday 01 December 2008 18:39:48 schrieb Luis R. Rodriguez:
> It would be nice to get this figured out before adding it. We got random
> complaints from users claiming 802.11n wasn't working before because
> iwconfig didn't report a good rate. Users will trust it so I'd rather
> see this go in with MCS rate figured out as part of the API to avoid
> such reports. Would it be possible for you to work on that?
>
> This might come in handy:
>
> http://wireless.kernel.org/en/developers/Documentation/ieee80211/802.11n#MC
>SRates
>
> What you need then is the guard interval, the MCS rate index and the
> number of streams being used for communication.

> Also how about we add a last TX rate and last RX rate so we get both?
>
>   Luis

Changes since v1:
- removed noise and quality from station info in NL80211
- added bandwith to station info in NL80211
- changed name of patch file to nl80211ext_v2.patch
 
Changes since v2:
- added kernel comment lines for new fields/enums
- changed name of "bandwith" field to tx_bitrate

Changes since v3:
- added rx_bitrate to station info and sta_info
- remember bitrate of last received unicast packet to this station
- decode 802.11n MCS index for nl80211
  (maybe this should be ported to WEXT too ?)

The last part is untested because I own only one 802.11n capable wlan device, 
so I cannot create an adhoc network with 802.11n, but I hope I got the code 
right. The four data arrays and sta_get_80211n_bitrate() should be maybe moved 
to another file, but I'm not sure where to put it.

I have attached a patched station.c for the iw command, so the changes can be
tested with "iw dev wlan0 station dump":

root@.....:~/iw.new# ./iw dev wlan0 station dump                                          
Station xx:xx:xx:xx:xx:xx (on wlan0)                                                       
        inactive time:  228 ms                                                             
        rx bytes:       4247                                                               
        tx bytes:       932                                                                
        signal:         -68 dBm                                                            
        rx-bitrate:     12.0 MBit/s                                                        
        tx-bitrate:     6.0 MBit/s                                                         

Henning

*************************************************
Diplom Informatiker Henning Rogge
Forschungsgesellschaft für
Angewandte Naturwissenschaften e. V. (FGAN) 
Neuenahrer Str. 20, 53343 Wachtberg, Germany
Tel.: 0049 (0)228 9435-961
Fax: 0049 (0)228 9435-685
E-Mail: rogge@fgan.de
Web: www.fgan.de
************************************************
Sitz der Gesellschaft: Bonn
Registergericht: Amtsgericht Bonn VR 2530
Vorstand: Dr. rer. nat. Ralf Dornhaus (Vors.), Prof. Dr. Joachim Ender 
(Stellv.)

--------------------------------------------------------
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index e08c8bc..3a83e97 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -404,6 +404,10 @@ enum nl80211_sta_flags {
  * @NL80211_STA_INFO_TX_BYTES: total transmitted bytes (u32, to this station)
  * @__NL80211_STA_INFO_AFTER_LAST: internal
  * @NL80211_STA_INFO_MAX: highest possible station info attribute
+ * @NL80211_STA_INFO_SIGNAL: signal strength of last received package (u8, 
dBm)
+ * @NL80211_STA_INFO_RX_BITRATE: bitrate of last received unicast packet
+ *  (u16, 100 kbit/s)
+ * @NL80211_STA_INFO_TX_BITRATE: current unicast tx rate (u16, 100 kbit/s)
  */
 enum nl80211_sta_info {
 	__NL80211_STA_INFO_INVALID,
@@ -413,6 +417,9 @@ enum nl80211_sta_info {
 	NL80211_STA_INFO_LLID,
 	NL80211_STA_INFO_PLID,
 	NL80211_STA_INFO_PLINK_STATE,
+	NL80211_STA_INFO_SIGNAL,
+	NL80211_STA_INFO_RX_BITRATE,
+	NL80211_STA_INFO_TX_BITRATE,
 
 	/* keep last */
 	__NL80211_STA_INFO_AFTER_LAST,
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 1d57835..cdf9433 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -167,6 +167,9 @@ struct station_parameters {
  * @STATION_INFO_LLID: @llid filled
  * @STATION_INFO_PLID: @plid filled
  * @STATION_INFO_PLINK_STATE: @plink_state filled
+ * @STATION_INFO_SIGNAL: @signal filled
+ * @STATION_INFO_RX_BITRATE: @rx_bitrate filled
+ * @STATION_INFO_TX_BITRATE: @tx_bitrate filled
  */
 enum station_info_flags {
 	STATION_INFO_INACTIVE_TIME	= 1<<0,
@@ -175,6 +178,9 @@ enum station_info_flags {
 	STATION_INFO_LLID		= 1<<3,
 	STATION_INFO_PLID		= 1<<4,
 	STATION_INFO_PLINK_STATE	= 1<<5,
+	STATION_INFO_SIGNAL		= 1<<6,
+	STATION_INFO_RX_BITRATE		= 1<<7,
+	STATION_INFO_TX_BITRATE		= 1<<8,
 };
 
 /**
@@ -189,6 +195,9 @@ enum station_info_flags {
  * @llid: mesh local link id
  * @plid: mesh peer link id
  * @plink_state: mesh peer link state
+ * @signal: signal strength of last received package in dBm
+ * @rx_bitrate: bitrate of last received unicast packet in 100 kbit/sec
+ * @tx_bitrate: current unicast tx rate in 100 kbit/sec
  */
 struct station_info {
 	u32 filled;
@@ -198,6 +207,9 @@ struct station_info {
 	u16 llid;
 	u16 plid;
 	u8 plink_state;
+	u8 signal;
+	u16 rx_bitrate;
+	u16 tx_bitrate;
 };
 
 /**
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 16423f9..77f0b1e 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -17,6 +17,41 @@
 #include "rate.h"
 #include "mesh.h"
 
+/* bitrate of 802.11n ht20 connections with 800ns guard interval in 100kbit/s 
*/
+const u16 ieee80211n_ht20_gi800[] = {
+    65, 130, 195, 260, 390, 520, 585, 650,
+    130, 260, 390, 520, 780, 1040, 1170, 1300,
+    195, 390, 585, 780, 1170, 1560, 1755, 1950,
+    260, 520, 780, 1040, 1560, 2080, 2340, 2600
+};
+
+/* bitrate of 802.11n ht20 connections with 400ns guard interval
+ * in 100kbit/s per spatial stream */
+const u16 ieee80211n_ht20_gi400[] = {
+    72, 144, 217, 289, 433, 578, 650, 722,
+    144, 289, 433, 578, 867, 1156, 1300, 1440,
+    217, 433, 650, 867, 1300, 1733, 1950, 2167,
+    289, 578, 867, 1157, 1733, 2311, 2600, 2889
+};
+
+/* bitrate of 802.11n ht40 connections with 800ns guard interval
+ * in 100kbit/s per spatial stream */
+const u16 ieee80211n_ht40_gi800[] = {
+    135, 270, 405, 540, 810, 1080, 1215, 1350,
+    270, 540, 810, 1080, 1620, 2160, 2430, 2700,
+    405, 810, 1215, 1620, 2430, 3240, 3645, 4050,
+    540, 1080, 1620, 2160, 3240, 4320, 4860, 5400
+};
+
+/* bitrate of 802.11n ht40 connections with 400ns guard interval
+ * in 100kbit/s per spatial stream */
+const u16 ieee80211n_ht40_gi400[] = {
+    150, 300, 450, 600, 900, 1200, 1350, 1500,
+    300, 600, 900, 1200, 1800, 2400, 2700, 3000,
+    450, 900, 1350, 1800, 2700, 3600, 4050, 4500,
+    600, 1200, 1800, 2400, 3600, 4800, 5400, 6000
+};
+
 static bool nl80211_type_check(enum nl80211_iftype type)
 {
 	switch (type) {
@@ -304,18 +339,50 @@ static int ieee80211_config_default_key(struct wiphy 
*wiphy,
 	return 0;
 }
 
+static u16 sta_get_80211n_bitrate(struct ieee80211_tx_rate *rate) {
+  if (!(rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH)) {
+    if (!(rate->flags & IEEE80211_TX_RC_SHORT_GI))
+      return ieee80211n_ht20_gi800[rate->idx];
+
+    return ieee80211n_ht20_gi400[rate->idx];
+  }
+  else {
+    if (!(rate->flags & IEEE80211_TX_RC_SHORT_GI))
+      return ieee80211n_ht40_gi800[rate->idx];
+
+    return ieee80211n_ht40_gi400[rate->idx];
+  }
+}
+
 static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
 {
 	struct ieee80211_sub_if_data *sdata = sta->sdata;
 
 	sinfo->filled = STATION_INFO_INACTIVE_TIME |
 			STATION_INFO_RX_BYTES |
-			STATION_INFO_TX_BYTES;
+			STATION_INFO_TX_BYTES |
+			STATION_INFO_RX_BITRATE |
+			STATION_INFO_TX_BITRATE;
 
 	sinfo->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx);
 	sinfo->rx_bytes = sta->rx_bytes;
 	sinfo->tx_bytes = sta->tx_bytes;
 
+	if (sta->local->hw.flags & IEEE80211_HW_SIGNAL_DBM) {
+	  sinfo->filled |= STATION_INFO_SIGNAL;
+	  sinfo->signal = sta->last_signal;
+	}
+
+	sinfo->rx_bitrate = sta->last_rxrate_unicast;
+
+	if (!(sta->last_tx_rate.flags & IEEE80211_TX_RC_MCS)) {
+	  struct ieee80211_supported_band *sband;
+	  sband = sta->local->hw.wiphy->bands[sta->local->hw.conf.channel->band];
+	  sinfo->tx_bitrate = sband->bitrates[sta->last_tx_rate.idx].bitrate;
+	}
+	else
+	  sinfo->tx_bitrate = sta_get_80211n_bitrate(&sta->last_tx_rate);
+
 	if (ieee80211_vif_is_mesh(&sdata->vif)) {
 #ifdef CONFIG_MAC80211_MESH
 		sinfo->filled |= STATION_INFO_LLID |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 5a1a60f..4b8ee9b 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -720,8 +720,15 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
 	if (rx->sdata->vif.type == NL80211_IFTYPE_ADHOC) {
 		u8 *bssid = ieee80211_get_bssid(hdr, rx->skb->len,
 						NL80211_IFTYPE_ADHOC);
-		if (compare_ether_addr(bssid, rx->sdata->u.sta.bssid) == 0)
+		if (compare_ether_addr(bssid, rx->sdata->u.sta.bssid) == 0) {
 			sta->last_rx = jiffies;
+
+			/* only update last_rxrate_unicast when we receive a
+			 * unicast packet for this station */
+			if (compare_ether_addr(hdr->addr1, sta->sta.addr)) {
+			  sta->last_rxrate_unicast = rx->rate->bitrate;
+			}
+		}
 	} else
 	if (!is_multicast_ether_addr(hdr->addr1) ||
 	    rx->sdata->vif.type == NL80211_IFTYPE_STATION) {
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index dc2606d..d2853ae 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -254,6 +254,7 @@ struct sta_info {
 	int last_signal;
 	int last_qual;
 	int last_noise;
+	u16 last_rxrate_unicast;
 	__le16 last_seq_ctrl[NUM_RX_DATA_QUEUES];
 
 	/* Updated from TX status path only, no locking requirements */
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index c9141e3..776e333 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -1057,6 +1057,15 @@ static int nl80211_send_station(struct sk_buff *msg, 
u32 pid, u32 seq,
 	if (sinfo->filled & STATION_INFO_PLINK_STATE)
 		NLA_PUT_U8(msg, NL80211_STA_INFO_PLINK_STATE,
 			    sinfo->plink_state);
+	if (sinfo->filled & STATION_INFO_SIGNAL)
+		NLA_PUT_U8(msg, NL80211_STA_INFO_SIGNAL,
+			    sinfo->signal);
+	if (sinfo->filled & STATION_INFO_RX_BITRATE)
+		NLA_PUT_U16(msg, NL80211_STA_INFO_RX_BITRATE,
+		            sinfo->rx_bitrate);
+	if (sinfo->filled & STATION_INFO_TX_BITRATE)
+		NLA_PUT_U16(msg, NL80211_STA_INFO_TX_BITRATE,
+		            sinfo->tx_bitrate);
 
 	nla_nest_end(msg, sinfoattr);
 


[-- Attachment #1.2: nl80211ext_v4.patch --]
[-- Type: text/x-patch, Size: 7761 bytes --]

diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index e08c8bc..3a83e97 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -404,6 +404,10 @@ enum nl80211_sta_flags {
  * @NL80211_STA_INFO_TX_BYTES: total transmitted bytes (u32, to this station)
  * @__NL80211_STA_INFO_AFTER_LAST: internal
  * @NL80211_STA_INFO_MAX: highest possible station info attribute
+ * @NL80211_STA_INFO_SIGNAL: signal strength of last received package (u8, dBm)
+ * @NL80211_STA_INFO_RX_BITRATE: bitrate of last received unicast packet
+ *  (u16, 100 kbit/s)
+ * @NL80211_STA_INFO_TX_BITRATE: current unicast tx rate (u16, 100 kbit/s)
  */
 enum nl80211_sta_info {
 	__NL80211_STA_INFO_INVALID,
@@ -413,6 +417,9 @@ enum nl80211_sta_info {
 	NL80211_STA_INFO_LLID,
 	NL80211_STA_INFO_PLID,
 	NL80211_STA_INFO_PLINK_STATE,
+	NL80211_STA_INFO_SIGNAL,
+	NL80211_STA_INFO_RX_BITRATE,
+	NL80211_STA_INFO_TX_BITRATE,
 
 	/* keep last */
 	__NL80211_STA_INFO_AFTER_LAST,
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 1d57835..cdf9433 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -167,6 +167,9 @@ struct station_parameters {
  * @STATION_INFO_LLID: @llid filled
  * @STATION_INFO_PLID: @plid filled
  * @STATION_INFO_PLINK_STATE: @plink_state filled
+ * @STATION_INFO_SIGNAL: @signal filled
+ * @STATION_INFO_RX_BITRATE: @rx_bitrate filled
+ * @STATION_INFO_TX_BITRATE: @tx_bitrate filled
  */
 enum station_info_flags {
 	STATION_INFO_INACTIVE_TIME	= 1<<0,
@@ -175,6 +178,9 @@ enum station_info_flags {
 	STATION_INFO_LLID		= 1<<3,
 	STATION_INFO_PLID		= 1<<4,
 	STATION_INFO_PLINK_STATE	= 1<<5,
+	STATION_INFO_SIGNAL		= 1<<6,
+	STATION_INFO_RX_BITRATE		= 1<<7,
+	STATION_INFO_TX_BITRATE		= 1<<8,
 };
 
 /**
@@ -189,6 +195,9 @@ enum station_info_flags {
  * @llid: mesh local link id
  * @plid: mesh peer link id
  * @plink_state: mesh peer link state
+ * @signal: signal strength of last received package in dBm
+ * @rx_bitrate: bitrate of last received unicast packet in 100 kbit/sec
+ * @tx_bitrate: current unicast tx rate in 100 kbit/sec
  */
 struct station_info {
 	u32 filled;
@@ -198,6 +207,9 @@ struct station_info {
 	u16 llid;
 	u16 plid;
 	u8 plink_state;
+	u8 signal;
+	u16 rx_bitrate;
+	u16 tx_bitrate;
 };
 
 /**
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 16423f9..77f0b1e 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -17,6 +17,41 @@
 #include "rate.h"
 #include "mesh.h"
 
+/* bitrate of 802.11n ht20 connections with 800ns guard interval in 100kbit/s */
+const u16 ieee80211n_ht20_gi800[] = {
+    65, 130, 195, 260, 390, 520, 585, 650,
+    130, 260, 390, 520, 780, 1040, 1170, 1300,
+    195, 390, 585, 780, 1170, 1560, 1755, 1950,
+    260, 520, 780, 1040, 1560, 2080, 2340, 2600
+};
+
+/* bitrate of 802.11n ht20 connections with 400ns guard interval
+ * in 100kbit/s per spatial stream */
+const u16 ieee80211n_ht20_gi400[] = {
+    72, 144, 217, 289, 433, 578, 650, 722,
+    144, 289, 433, 578, 867, 1156, 1300, 1440,
+    217, 433, 650, 867, 1300, 1733, 1950, 2167,
+    289, 578, 867, 1157, 1733, 2311, 2600, 2889
+};
+
+/* bitrate of 802.11n ht40 connections with 800ns guard interval
+ * in 100kbit/s per spatial stream */
+const u16 ieee80211n_ht40_gi800[] = {
+    135, 270, 405, 540, 810, 1080, 1215, 1350,
+    270, 540, 810, 1080, 1620, 2160, 2430, 2700,
+    405, 810, 1215, 1620, 2430, 3240, 3645, 4050,
+    540, 1080, 1620, 2160, 3240, 4320, 4860, 5400
+};
+
+/* bitrate of 802.11n ht40 connections with 400ns guard interval
+ * in 100kbit/s per spatial stream */
+const u16 ieee80211n_ht40_gi400[] = {
+    150, 300, 450, 600, 900, 1200, 1350, 1500,
+    300, 600, 900, 1200, 1800, 2400, 2700, 3000,
+    450, 900, 1350, 1800, 2700, 3600, 4050, 4500,
+    600, 1200, 1800, 2400, 3600, 4800, 5400, 6000
+};
+
 static bool nl80211_type_check(enum nl80211_iftype type)
 {
 	switch (type) {
@@ -304,18 +339,50 @@ static int ieee80211_config_default_key(struct wiphy *wiphy,
 	return 0;
 }
 
+static u16 sta_get_80211n_bitrate(struct ieee80211_tx_rate *rate) {
+  if (!(rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH)) {
+    if (!(rate->flags & IEEE80211_TX_RC_SHORT_GI))
+      return ieee80211n_ht20_gi800[rate->idx];
+
+    return ieee80211n_ht20_gi400[rate->idx];
+  }
+  else {
+    if (!(rate->flags & IEEE80211_TX_RC_SHORT_GI))
+      return ieee80211n_ht40_gi800[rate->idx];
+
+    return ieee80211n_ht40_gi400[rate->idx];
+  }
+}
+
 static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
 {
 	struct ieee80211_sub_if_data *sdata = sta->sdata;
 
 	sinfo->filled = STATION_INFO_INACTIVE_TIME |
 			STATION_INFO_RX_BYTES |
-			STATION_INFO_TX_BYTES;
+			STATION_INFO_TX_BYTES |
+			STATION_INFO_RX_BITRATE |
+			STATION_INFO_TX_BITRATE;
 
 	sinfo->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx);
 	sinfo->rx_bytes = sta->rx_bytes;
 	sinfo->tx_bytes = sta->tx_bytes;
 
+	if (sta->local->hw.flags & IEEE80211_HW_SIGNAL_DBM) {
+	  sinfo->filled |= STATION_INFO_SIGNAL;
+	  sinfo->signal = sta->last_signal;
+	}
+
+	sinfo->rx_bitrate = sta->last_rxrate_unicast;
+
+	if (!(sta->last_tx_rate.flags & IEEE80211_TX_RC_MCS)) {
+	  struct ieee80211_supported_band *sband;
+	  sband = sta->local->hw.wiphy->bands[sta->local->hw.conf.channel->band];
+	  sinfo->tx_bitrate = sband->bitrates[sta->last_tx_rate.idx].bitrate;
+	}
+	else
+	  sinfo->tx_bitrate = sta_get_80211n_bitrate(&sta->last_tx_rate);
+
 	if (ieee80211_vif_is_mesh(&sdata->vif)) {
 #ifdef CONFIG_MAC80211_MESH
 		sinfo->filled |= STATION_INFO_LLID |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 5a1a60f..4b8ee9b 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -720,8 +720,15 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
 	if (rx->sdata->vif.type == NL80211_IFTYPE_ADHOC) {
 		u8 *bssid = ieee80211_get_bssid(hdr, rx->skb->len,
 						NL80211_IFTYPE_ADHOC);
-		if (compare_ether_addr(bssid, rx->sdata->u.sta.bssid) == 0)
+		if (compare_ether_addr(bssid, rx->sdata->u.sta.bssid) == 0) {
 			sta->last_rx = jiffies;
+
+			/* only update last_rxrate_unicast when we receive a
+			 * unicast packet for this station */
+			if (compare_ether_addr(hdr->addr1, sta->sta.addr)) {
+			  sta->last_rxrate_unicast = rx->rate->bitrate;
+			}
+		}
 	} else
 	if (!is_multicast_ether_addr(hdr->addr1) ||
 	    rx->sdata->vif.type == NL80211_IFTYPE_STATION) {
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index dc2606d..d2853ae 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -254,6 +254,7 @@ struct sta_info {
 	int last_signal;
 	int last_qual;
 	int last_noise;
+	u16 last_rxrate_unicast;
 	__le16 last_seq_ctrl[NUM_RX_DATA_QUEUES];
 
 	/* Updated from TX status path only, no locking requirements */
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index c9141e3..776e333 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -1057,6 +1057,15 @@ static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
 	if (sinfo->filled & STATION_INFO_PLINK_STATE)
 		NLA_PUT_U8(msg, NL80211_STA_INFO_PLINK_STATE,
 			    sinfo->plink_state);
+	if (sinfo->filled & STATION_INFO_SIGNAL)
+		NLA_PUT_U8(msg, NL80211_STA_INFO_SIGNAL,
+			    sinfo->signal);
+	if (sinfo->filled & STATION_INFO_RX_BITRATE)
+		NLA_PUT_U16(msg, NL80211_STA_INFO_RX_BITRATE,
+		            sinfo->rx_bitrate);
+	if (sinfo->filled & STATION_INFO_TX_BITRATE)
+		NLA_PUT_U16(msg, NL80211_STA_INFO_TX_BITRATE,
+		            sinfo->tx_bitrate);
 
 	nla_nest_end(msg, sinfoattr);
 

[-- Attachment #1.3: station.c --]
[-- Type: text/x-csrc, Size: 5653 bytes --]

#include <net/if.h>
#include <errno.h>
#include <string.h>

#include <netlink/genl/genl.h>
#include <netlink/genl/family.h>
#include <netlink/genl/ctrl.h>
#include <netlink/msg.h>
#include <netlink/attr.h>

#include "nl80211.h"
#include "iw.h"

enum plink_state {
	LISTEN,
	OPN_SNT,
	OPN_RCVD,
	CNF_RCVD,
	ESTAB,
	HOLDING,
	BLOCKED
};

enum plink_actions {
	PLINK_ACTION_UNDEFINED,
	PLINK_ACTION_OPEN,
	PLINK_ACTION_BLOCK,
};


static int print_sta_handler(struct nl_msg *msg, void *arg)
{
	struct nlattr *tb[NL80211_ATTR_MAX + 1];
	struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
	struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
	char mac_addr[20], state_name[10], dev[20];
	static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
		[NL80211_STA_INFO_INACTIVE_TIME] = { .type = NLA_U32 },
		[NL80211_STA_INFO_RX_BYTES] = { .type = NLA_U32 },
		[NL80211_STA_INFO_TX_BYTES] = { .type = NLA_U32 },
		[NL80211_STA_INFO_LLID] = { .type = NLA_U16 },
		[NL80211_STA_INFO_PLID] = { .type = NLA_U16 },
		[NL80211_STA_INFO_PLINK_STATE] = { .type = NLA_U8 },
		[NL80211_STA_INFO_SIGNAL] = { .type = NLA_U8 },
		[NL80211_STA_INFO_RX_BITRATE] = { .type = NLA_U16 },
		[NL80211_STA_INFO_TX_BITRATE] = { .type = NLA_U16 },
	};

	nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
		  genlmsg_attrlen(gnlh, 0), NULL);

	/*
	 * TODO: validate the interface and mac address!
	 * Otherwise, there's a race condition as soon as
	 * the kernel starts sending station notifications.
	 */

	if (!tb[NL80211_ATTR_STA_INFO]) {
		fprintf(stderr, "sta stats missing!");
		return NL_SKIP;
	}
	if (nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,
			     tb[NL80211_ATTR_STA_INFO],
			     stats_policy)) {
		fprintf(stderr, "failed to parse nested attributes!");
		return NL_SKIP;
	}

	mac_addr_n2a(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
	if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
	printf("Station %s (on %s)", mac_addr, dev);

	if (sinfo[NL80211_STA_INFO_INACTIVE_TIME])
		printf("\n\tinactive time:\t%d ms",
			nla_get_u32(sinfo[NL80211_STA_INFO_INACTIVE_TIME]));
	if (sinfo[NL80211_STA_INFO_RX_BYTES])
		printf("\n\trx bytes:\t%d",
			nla_get_u32(sinfo[NL80211_STA_INFO_RX_BYTES]));
	if (sinfo[NL80211_STA_INFO_TX_BYTES])
		printf("\n\ttx bytes:\t%d",
			nla_get_u32(sinfo[NL80211_STA_INFO_TX_BYTES]));
	if (sinfo[NL80211_STA_INFO_SIGNAL])
		printf("\n\tsignal:  \t%d dBm",
			(int8_t)nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]));
	if (sinfo[NL80211_STA_INFO_RX_BITRATE]) {
		int bitrate = nla_get_u16(sinfo[NL80211_STA_INFO_RX_BITRATE]);
		printf("\n\trx-bitrate:\t%d.%01d MBit/s", bitrate/10, bitrate % 10);
	}
	if (sinfo[NL80211_STA_INFO_TX_BITRATE]) {
		int bitrate = nla_get_u16(sinfo[NL80211_STA_INFO_TX_BITRATE]);
		printf("\n\ttx-bitrate:\t%d.%01d MBit/s", bitrate/10, bitrate % 10);
	}
	if (sinfo[NL80211_STA_INFO_LLID])
		printf("\n\tmesh llid:\t%d",
			nla_get_u16(sinfo[NL80211_STA_INFO_LLID]));
	if (sinfo[NL80211_STA_INFO_PLID])
		printf("\n\tmesh plid:\t%d",
			nla_get_u16(sinfo[NL80211_STA_INFO_PLID]));
	if (sinfo[NL80211_STA_INFO_PLINK_STATE]) {
		switch (nla_get_u16(sinfo[NL80211_STA_INFO_PLINK_STATE])) {
		case LISTEN:
			strcpy(state_name, "LISTEN");
			break;
		case OPN_SNT:
			strcpy(state_name, "OPN_SNT");
			break;
		case OPN_RCVD:
			strcpy(state_name, "OPN_RCVD");
			break;
		case CNF_RCVD:
			strcpy(state_name, "CNF_RCVD");
			break;
		case ESTAB:
			strcpy(state_name, "ESTAB");
			break;
		case HOLDING:
			strcpy(state_name, "HOLDING");
			break;
		case BLOCKED:
			strcpy(state_name, "BLOCKED");
			break;
		default:
			strcpy(state_name, "UNKNOWN");
			break;
		}
		printf("\n\tmesh plink:\t%s", state_name);
	}

	printf("\n");
	return NL_SKIP;
}

static int handle_station_get(struct nl_cb *cb,
			      struct nl_msg *msg,
			      int argc, char **argv)
{
	unsigned char mac_addr[ETH_ALEN];

	if (argc < 1)
		return 1;

	if (mac_addr_a2n(mac_addr, argv[0])) {
		fprintf(stderr, "invalid mac address\n");
		return 2;
	}

	argc--;
	argv++;

	if (argc)
		return 1;

	NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr);

	nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, print_sta_handler, NULL);

	return 0;
 nla_put_failure:
	return -ENOBUFS;
}
COMMAND(station, get, "<MAC address>",
	NL80211_CMD_GET_STATION, 0, CIB_NETDEV, handle_station_get);
COMMAND(station, del, "<MAC address>",
	NL80211_CMD_DEL_STATION, 0, CIB_NETDEV, handle_station_get);

static int handle_station_set(struct nl_cb *cb,
			      struct nl_msg *msg,
			      int argc, char **argv)
{
	unsigned char plink_action;
	unsigned char mac_addr[ETH_ALEN];

	if (argc < 3)
		return 1;

	if (mac_addr_a2n(mac_addr, argv[0])) {
		fprintf(stderr, "invalid mac address\n");
		return 2;
	}
	argc--;
	argv++;

	if (strcmp("plink_action", argv[0]) != 0)
		return 1;
	argc--;
	argv++;

	if (strcmp("open", argv[0]) == 0)
		plink_action = PLINK_ACTION_OPEN;
	else if (strcmp("block", argv[0]) == 0)
		plink_action = PLINK_ACTION_BLOCK;
	else {
		fprintf(stderr, "plink action not supported\n");
		return 2;
	}
	argc--;
	argv++;

	if (argc)
		return 1;

	NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr);
	NLA_PUT_U8(msg, NL80211_ATTR_STA_PLINK_ACTION, plink_action);

	return 0;
 nla_put_failure:
	return -ENOBUFS;
}
COMMAND(station, set, "<MAC address> plink_action <open|block>",
	NL80211_CMD_SET_STATION, 0, CIB_NETDEV, handle_station_set);

static int handle_station_dump(struct nl_cb *cb,
			       struct nl_msg *msg,
			       int argc, char **argv)
{
	nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, print_sta_handler, NULL);
	return 0;
}
COMMAND(station, dump, NULL,
	NL80211_CMD_GET_STATION, NLM_F_DUMP, CIB_NETDEV, handle_station_dump);

[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 197 bytes --]

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

* Re: RFC Patch v2: Add signal strength to nl80211station info
  2008-12-02 13:25             ` Henning Rogge
@ 2008-12-02 20:29               ` Luis R. Rodriguez
  2008-12-02 20:46                 ` Henning Rogge
  0 siblings, 1 reply; 66+ messages in thread
From: Luis R. Rodriguez @ 2008-12-02 20:29 UTC (permalink / raw)
  To: Henning Rogge
  Cc: Luis Rodriguez, Johannes Berg, Henning Rogge, Marcel Holtmann,
	linux-wireless, nbd

On Tue, Dec 02, 2008 at 05:25:36AM -0800, Henning Rogge wrote:
> diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
> index e08c8bc..3a83e97 100644
> --- a/include/linux/nl80211.h
> +++ b/include/linux/nl80211.h
> @@ -404,6 +404,10 @@ enum nl80211_sta_flags {
>   * @NL80211_STA_INFO_TX_BYTES: total transmitted bytes (u32, to this station)
>   * @__NL80211_STA_INFO_AFTER_LAST: internal
>   * @NL80211_STA_INFO_MAX: highest possible station info attribute
> + * @NL80211_STA_INFO_SIGNAL: signal strength of last received package (u8, 
> dBm)

Shouldn't this be s8?

> diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
> index 1d57835..cdf9433 100644
> --- a/include/net/cfg80211.h
> +++ b/include/net/cfg80211.h
> @@ -167,6 +167,9 @@ struct station_parameters {
>   * @STATION_INFO_LLID: @llid filled
>   * @STATION_INFO_PLID: @plid filled
>   * @STATION_INFO_PLINK_STATE: @plink_state filled
> + * @STATION_INFO_SIGNAL: @signal filled

Can you extend this to indicate drivers which enable this must
pass the singal in dBm (IEEE80211_HW_SIGNAL_DBM for mac80211 drivers)
as that is what cfg80211 expects?

This is important as mac80211 drivers not using IEEE80211_HW_SIGNAL_DBM
will luck out of getting signal reports. This means these drivers won't
get signal reports right now:

adm8211.c:1865: dev->flags = IEEE80211_HW_SIGNAL_UNSPEC;
rtl818x/rtl8187_dev.c:1416:             dev->flags |= IEEE80211_HW_SIGNAL_UNSPEC;
rtl818x/rtl8180_dev.c:900:                   IEEE80211_HW_SIGNAL_UNSPEC;
zd1211rw/zd_mac.c:972:              IEEE80211_HW_SIGNAL_DB;

I guess this is the iffy part... I'll see if zd1211rw can somehow use
dBm though.

> diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
> index 16423f9..77f0b1e 100644
> --- a/net/mac80211/cfg.c
> +++ b/net/mac80211/cfg.c
> @@ -17,6 +17,41 @@
>  #include "rate.h"
>  #include "mesh.h"
>  
> +/* bitrate of 802.11n ht20 connections with 800ns guard interval in 100kbit/s 
> */
> +const u16 ieee80211n_ht20_gi800[] = {
> +    65, 130, 195, 260, 390, 520, 585, 650,
> +    130, 260, 390, 520, 780, 1040, 1170, 1300,
> +    195, 390, 585, 780, 1170, 1560, 1755, 1950,
> +    260, 520, 780, 1040, 1560, 2080, 2340, 2600
> +};
> +
> +/* bitrate of 802.11n ht20 connections with 400ns guard interval
> + * in 100kbit/s per spatial stream */
> +const u16 ieee80211n_ht20_gi400[] = {
> +    72, 144, 217, 289, 433, 578, 650, 722,
> +    144, 289, 433, 578, 867, 1156, 1300, 1440,
> +    217, 433, 650, 867, 1300, 1733, 1950, 2167,
> +    289, 578, 867, 1157, 1733, 2311, 2600, 2889
> +};
> +
> +/* bitrate of 802.11n ht40 connections with 800ns guard interval
> + * in 100kbit/s per spatial stream */
> +const u16 ieee80211n_ht40_gi800[] = {
> +    135, 270, 405, 540, 810, 1080, 1215, 1350,
> +    270, 540, 810, 1080, 1620, 2160, 2430, 2700,
> +    405, 810, 1215, 1620, 2430, 3240, 3645, 4050,
> +    540, 1080, 1620, 2160, 3240, 4320, 4860, 5400
> +};
> +
> +/* bitrate of 802.11n ht40 connections with 400ns guard interval
> + * in 100kbit/s per spatial stream */
> +const u16 ieee80211n_ht40_gi400[] = {
> +    150, 300, 450, 600, 900, 1200, 1350, 1500,
> +    300, 600, 900, 1200, 1800, 2400, 2700, 3000,
> +    450, 900, 1350, 1800, 2700, 3600, 4050, 4500,
> +    600, 1200, 1800, 2400, 3600, 4800, 5400, 6000
> +};
> +

Awesome stuff, now come to think of it, perhaps its best we let
userspace do the calculation and we just give it the last RX/TX
guard interval and the MCS index? Technically speaking it seems
we don't have duplicate rates though so a reverse map is possible
but it seems useful to just provide the information directly.

Any thoughts?

  Luis

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

* Re: RFC Patch v2: Add signal strength to nl80211station info
  2008-12-02 20:29               ` Luis R. Rodriguez
@ 2008-12-02 20:46                 ` Henning Rogge
  2008-12-03  1:44                   ` Luis R. Rodriguez
  0 siblings, 1 reply; 66+ messages in thread
From: Henning Rogge @ 2008-12-02 20:46 UTC (permalink / raw)
  To: Luis R. Rodriguez, Johannes Berg
  Cc: Henning Rogge, Marcel Holtmann, linux-wireless, nbd

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

> > @@ -404,6 +404,10 @@ enum nl80211_sta_flags {
> >   * @NL80211_STA_INFO_TX_BYTES: total transmitted bytes (u32, to this
> > station) * @__NL80211_STA_INFO_AFTER_LAST: internal
> >   * @NL80211_STA_INFO_MAX: highest possible station info attribute
> > + * @NL80211_STA_INFO_SIGNAL: signal strength of last received package
> > (u8, dBm)
> Shouldn't this be s8?
I did not find macros for nl80211 to add signed values... so its just "say 
it's signed, but use the unsigned macro" ? If yes I will change the 
documentation.

> > diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
> > index 1d57835..cdf9433 100644
> > --- a/include/net/cfg80211.h
> > +++ b/include/net/cfg80211.h
> > @@ -167,6 +167,9 @@ struct station_parameters {
> >   * @STATION_INFO_LLID: @llid filled
> >   * @STATION_INFO_PLID: @plid filled
> >   * @STATION_INFO_PLINK_STATE: @plink_state filled
> > + * @STATION_INFO_SIGNAL: @signal filled
>
> Can you extend this to indicate drivers which enable this must
> pass the singal in dBm (IEEE80211_HW_SIGNAL_DBM for mac80211 drivers)
> as that is what cfg80211 expects?
The flag is only set if the driver sets the IEEE80211_HW_SIGNAL_DBM flag.
cfg.c:
+       if (sta->local->hw.flags & IEEE80211_HW_SIGNAL_DBM) {
+         sinfo->filled |= STATION_INFO_SIGNAL;
+         sinfo->signal = sta->last_signal;
+       }

But it might be better to explain this in the documentation.

> This is important as mac80211 drivers not using IEEE80211_HW_SIGNAL_DBM
> will luck out of getting signal reports. This means these drivers won't
> get signal reports right now:
I know... (did search for the HW_SIGNAL flags in the drivers)

> I guess this is the iffy part... I'll see if zd1211rw can somehow use
> dBm though.
That would be good I think.

> Awesome stuff, now come to think of it, perhaps its best we let
> userspace do the calculation and we just give it the last RX/TX
> guard interval and the MCS index? Technically speaking it seems
> we don't have duplicate rates though so a reverse map is possible
> but it seems useful to just provide the information directly.
 the problem of this approach would be that every userspace calculation would 
have to do this calculation on it's own. Whats about transmitting "basic 
datarate", "number of spatial streams" and "flags" (short/long GI, 20/40 Mhz 
width) to userspace ? This way it would be just a multiplication to get the 
total bandwith, but it still can easily be reverse mapped into MCS with some 
arithmetics.

Henning


[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 197 bytes --]

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

* Re: RFC Patch v2: Add signal strength to nl80211station info
  2008-12-02 20:46                 ` Henning Rogge
@ 2008-12-03  1:44                   ` Luis R. Rodriguez
  2008-12-03 10:31                     ` Henning Rogge
  0 siblings, 1 reply; 66+ messages in thread
From: Luis R. Rodriguez @ 2008-12-03  1:44 UTC (permalink / raw)
  To: Henning Rogge
  Cc: Luis Rodriguez, Johannes Berg, Henning Rogge, Marcel Holtmann,
	linux-wireless, nbd

On Tue, Dec 02, 2008 at 12:46:06PM -0800, Henning Rogge wrote:
> > > @@ -404,6 +404,10 @@ enum nl80211_sta_flags {
> > >   * @NL80211_STA_INFO_TX_BYTES: total transmitted bytes (u32, to =
this
> > > station) * @__NL80211_STA_INFO_AFTER_LAST: internal
> > >   * @NL80211_STA_INFO_MAX: highest possible station info attribut=
e
> > > + * @NL80211_STA_INFO_SIGNAL: signal strength of last received pa=
ckage
> > > (u8, dBm)
> > Shouldn't this be s8?
> I did not find macros for nl80211 to add signed values... so its just=
 "say=20
> it's signed, but use the unsigned macro" ? If yes I will change the=20
> documentation.

Ah no, nevermind me, netlink doesn't have singed values.

> > > diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
> > > index 1d57835..cdf9433 100644
> > > --- a/include/net/cfg80211.h
> > > +++ b/include/net/cfg80211.h
> > > @@ -167,6 +167,9 @@ struct station_parameters {
> > >   * @STATION_INFO_LLID: @llid filled
> > >   * @STATION_INFO_PLID: @plid filled
> > >   * @STATION_INFO_PLINK_STATE: @plink_state filled
> > > + * @STATION_INFO_SIGNAL: @signal filled
> >
> > Can you extend this to indicate drivers which enable this must
> > pass the singal in dBm (IEEE80211_HW_SIGNAL_DBM for mac80211 driver=
s)
> > as that is what cfg80211 expects?
> The flag is only set if the driver sets the IEEE80211_HW_SIGNAL_DBM f=
lag.
> cfg.c:
> +=A0=A0=A0=A0=A0=A0=A0if (sta->local->hw.flags & IEEE80211_HW_SIGNAL_=
DBM) {
> +=A0=A0=A0=A0=A0=A0=A0 =A0sinfo->filled |=3D STATION_INFO_SIGNAL;
> +=A0=A0=A0=A0=A0=A0=A0 =A0sinfo->signal =3D sta->last_signal;
> +=A0=A0=A0=A0=A0=A0=A0}
>=20
> But it might be better to explain this in the documentation.

Right.

> > This is important as mac80211 drivers not using IEEE80211_HW_SIGNAL=
_DBM
> > will luck out of getting signal reports. This means these drivers w=
on't
> > get signal reports right now:
> I know... (did search for the HW_SIGNAL flags in the drivers)
>=20
> > I guess this is the iffy part... I'll see if zd1211rw can somehow u=
se
> > dBm though.
> That would be good I think.
>=20
> > Awesome stuff, now come to think of it, perhaps its best we let
> > userspace do the calculation and we just give it the last RX/TX
> > guard interval and the MCS index? Technically speaking it seems
> > we don't have duplicate rates though so a reverse map is possible
> > but it seems useful to just provide the information directly.
>  the problem of this approach would be that every userspace calculati=
on would=20
> have to do this calculation on it's own.

True..

> Whats about transmitting "basic=20
> datarate"

What's that?

> , "number of spatial streams"

No need for this one, the HT mode (ht20 or ht40) and MCS index would
give us that.

> and "flags" (short/long GI, 20/40 Mhz  width) to userspace ?

Well... see below.

> This way it would be just a multiplication to get the=20
> total bandwith, but it still can easily be reverse mapped into MCS wi=
th some=20
> arithmetics.

I believe to get the throughput you need a lot more info than this, hen=
ce
why the table is so big and why you have array index for each MCS index
for each HT mode and guard interval.

So... what if we pass the throughput as you have it but also pass the
other stuff (flags, and MCS index) just so all userspace apps that
want to get last TX/RX guard interval, HT20/HT40, and MCS index
doesn't have to have a funky reverse map to get the flags and MCS index=
?

  Luis
--
To unsubscribe from this list: send the line "unsubscribe linux-wireles=
s" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: RFC Patch v2: Add signal strength to nl80211station info
  2008-12-03  1:44                   ` Luis R. Rodriguez
@ 2008-12-03 10:31                     ` Henning Rogge
  2008-12-04  8:47                       ` Johannes Berg
  2008-12-04 20:26                       ` Johannes Berg
  0 siblings, 2 replies; 66+ messages in thread
From: Henning Rogge @ 2008-12-03 10:31 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: Henning Rogge, Luis Rodriguez, Johannes Berg, Marcel Holtmann,
	linux-wireless, nbd


[-- Attachment #1.1: Type: text/plain, Size: 12349 bytes --]

Am Wednesday 03 December 2008 02:44:30 schrieb Luis R. Rodriguez:
> So... what if we pass the throughput as you have it but also pass the
> other stuff (flags, and MCS index) just so all userspace apps that
> want to get last TX/RX guard interval, HT20/HT40, and MCS index
> doesn't have to have a funky reverse map to get the flags and MCS index?

Changes since v1:
- removed noise and quality from station info in NL80211
- added bandwith to station info in NL80211
- changed name of patch file to nl80211ext_v2.patch
 
Changes since v2:
- added kernel comment lines for new fields/enums
- changed name of "bandwith" field to tx_bitrate

Changes since v3:
- added rx_bitrate to station info and sta_info
- remember bitrate of last received unicast packet to this station
- decode 802.11n MCS index for nl80211
  (maybe this should be ported to WEXT too ?)

Changes since v4:
- added tx_bitrate_flags adn tx_bitrate_mcs field to station info
- added flags for 40Mhz and small guard interval to NL80211 station info
- added mcs field to NL80211 station info

The IEEE80211_TX_RC_40_MHZ_WIDTH flag in nl80211 should work for 802.11g 
"turbomodes" and 802.11n, the IEEE80211_TX_RC_SHORT_GI is only available if 
the NL80211_STA_INFO_TX_BITRATE_MCS index is set too. All three fields will be 
only available if the STATION_INFO_TX_BITRATE field is set. (see station.c)

The whole 802.11n stuff is only compile-tested, but the code works on an 
atheros 802.11g card.

What do you think about the idea to export the 802.11n transmission rate 
through the old WExt interface, so iwconfig will show the correct rate too ? 
But for this the "mcs to bitrate" tables would have to be moved to some other 
file, so wext.c can access them too (which one ?).

Henning Rogge

*************************************************
Diplom Informatiker Henning Rogge
Forschungsgesellschaft für
Angewandte Naturwissenschaften e. V. (FGAN) 
Neuenahrer Str. 20, 53343 Wachtberg, Germany
Tel.: 0049 (0)228 9435-961
Fax: 0049 (0)228 9435-685
E-Mail: rogge@fgan.de
Web: www.fgan.de
************************************************
Sitz der Gesellschaft: Bonn
Registergericht: Amtsgericht Bonn VR 2530
Vorstand: Dr. rer. nat. Ralf Dornhaus (Vors.), Prof. Dr. Joachim Ender 
(Stellv.)

-------------------------------------------------------
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index e08c8bc..32bb7ad 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -404,6 +404,14 @@ enum nl80211_sta_flags {
  * @NL80211_STA_INFO_TX_BYTES: total transmitted bytes (u32, to this station)
  * @__NL80211_STA_INFO_AFTER_LAST: internal
  * @NL80211_STA_INFO_MAX: highest possible station info attribute
+ * @NL80211_STA_INFO_SIGNAL: signal strength of last received package (u8, 
dBm)
+ * @NL80211_STA_INFO_RX_BITRATE: bitrate of last received unicast packet
+ *  (u16, 100 kbit/s)
+ * @NL80211_STA_INFO_TX_BITRATE: current unicast tx rate (u16, 100 kbit/s)
+ * @NL80211_STA_INFO_TX_BITRATE_40_MHZ: dual channel transmission (flag)
+ * @NL80211_STA_INFO_TX_BITRATE_MCS: 802.11n MCS index of tx rate (u8)
+ * @NL80211_STA_INFO_TX_BITRATE_SHORT_GI: 802.11n with 400ns GI, 800ns
+ *  otherwise, should be ignored if TX_BITRATE_MCS is not set (flag)
  */
 enum nl80211_sta_info {
 	__NL80211_STA_INFO_INVALID,
@@ -413,6 +421,12 @@ enum nl80211_sta_info {
 	NL80211_STA_INFO_LLID,
 	NL80211_STA_INFO_PLID,
 	NL80211_STA_INFO_PLINK_STATE,
+	NL80211_STA_INFO_SIGNAL,
+	NL80211_STA_INFO_RX_BITRATE,
+	NL80211_STA_INFO_TX_BITRATE,
+	NL80211_STA_INFO_TX_BITRATE_40_MHZ,
+	NL80211_STA_INFO_TX_BITRATE_MCS,
+	NL80211_STA_INFO_TX_BITRATE_SHORT_GI,
 
 	/* keep last */
 	__NL80211_STA_INFO_AFTER_LAST,
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 1d57835..5cc8b53 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -160,6 +160,8 @@ struct station_parameters {
  *
  * Used by the driver to indicate which info in &struct station_info
  * it has filled in during get_station() or dump_station().
+ * Signal strength is only available if driver supports dBm signal
+ * strength.
  *
  * @STATION_INFO_INACTIVE_TIME: @inactive_time filled
  * @STATION_INFO_RX_BYTES: @rx_bytes filled
@@ -167,6 +169,10 @@ struct station_parameters {
  * @STATION_INFO_LLID: @llid filled
  * @STATION_INFO_PLID: @plid filled
  * @STATION_INFO_PLINK_STATE: @plink_state filled
+ * @STATION_INFO_SIGNAL: @signal filled
+ * @STATION_INFO_RX_BITRATE: @rx_bitrate filled
+ * @STATION_INFO_TX_BITRATE: @tx_bitrate fields are filled
+ *  (tx_bitrate, tx_bitrate_flags and tx_bitrate_mcs)
  */
 enum station_info_flags {
 	STATION_INFO_INACTIVE_TIME	= 1<<0,
@@ -175,6 +181,9 @@ enum station_info_flags {
 	STATION_INFO_LLID		= 1<<3,
 	STATION_INFO_PLID		= 1<<4,
 	STATION_INFO_PLINK_STATE	= 1<<5,
+	STATION_INFO_SIGNAL		= 1<<6,
+	STATION_INFO_RX_BITRATE		= 1<<7,
+	STATION_INFO_TX_BITRATE		= 1<<8,
 };
 
 /**
@@ -189,6 +198,15 @@ enum station_info_flags {
  * @llid: mesh local link id
  * @plid: mesh peer link id
  * @plink_state: mesh peer link state
+ * @signal: signal strength of last received package in dBm
+ * @rx_bitrate: bitrate of last received unicast packet in 100 kbit/sec
+ * @tx_bitrate: current unicast bitrate to this station in 100 kbit/sec
+ * @tx_bitrate_flags: a binary field with a combination of flags
+ *  IEEE80211_TX_RC_MCS: bitrate_mcs field contains the 802.11n MCS number
+ *  IEEE80211_TX_RC_40_MHZ_WIDTH: 40 Mhz wide channel, 20 Mhz if not set
+ *  IEEE80211_TX_RC_SHORT_GI: 400ns guard interval, 800ns if not set
+ * @tx_bitrate_mcs: if IEEE80211_TX_RC_MCS is set this is the MCS index
+ *  of a 802.11n transmission, if not it is set to zero
  */
 struct station_info {
 	u32 filled;
@@ -198,6 +216,10 @@ struct station_info {
 	u16 llid;
 	u16 plid;
 	u8 plink_state;
+	u8 signal;
+	u16 rx_bitrate;
+	u16 tx_bitrate;
+	u8 tx_bitrate_flags, tx_bitrate_mcs;
 };
 
 /**
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 16423f9..dc684a4 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -17,6 +17,41 @@
 #include "rate.h"
 #include "mesh.h"
 
+/* bitrate of 802.11n ht20 connections with 800ns guard interval in 100kbit/s 
*/
+const u16 ieee80211n_ht20_gi800[] = {
+    65, 130, 195, 260, 390, 520, 585, 650,
+    130, 260, 390, 520, 780, 1040, 1170, 1300,
+    195, 390, 585, 780, 1170, 1560, 1755, 1950,
+    260, 520, 780, 1040, 1560, 2080, 2340, 2600
+};
+
+/* bitrate of 802.11n ht20 connections with 400ns guard interval
+ * in 100kbit/s per spatial stream */
+const u16 ieee80211n_ht20_gi400[] = {
+    72, 144, 217, 289, 433, 578, 650, 722,
+    144, 289, 433, 578, 867, 1156, 1300, 1440,
+    217, 433, 650, 867, 1300, 1733, 1950, 2167,
+    289, 578, 867, 1157, 1733, 2311, 2600, 2889
+};
+
+/* bitrate of 802.11n ht40 connections with 800ns guard interval
+ * in 100kbit/s per spatial stream */
+const u16 ieee80211n_ht40_gi800[] = {
+    135, 270, 405, 540, 810, 1080, 1215, 1350,
+    270, 540, 810, 1080, 1620, 2160, 2430, 2700,
+    405, 810, 1215, 1620, 2430, 3240, 3645, 4050,
+    540, 1080, 1620, 2160, 3240, 4320, 4860, 5400
+};
+
+/* bitrate of 802.11n ht40 connections with 400ns guard interval
+ * in 100kbit/s per spatial stream */
+const u16 ieee80211n_ht40_gi400[] = {
+    150, 300, 450, 600, 900, 1200, 1350, 1500,
+    300, 600, 900, 1200, 1800, 2400, 2700, 3000,
+    450, 900, 1350, 1800, 2700, 3600, 4050, 4500,
+    600, 1200, 1800, 2400, 3600, 4800, 5400, 6000
+};
+
 static bool nl80211_type_check(enum nl80211_iftype type)
 {
 	switch (type) {
@@ -304,18 +339,58 @@ static int ieee80211_config_default_key(struct wiphy 
*wiphy,
 	return 0;
 }
 
+static u16 sta_get_80211n_bitrate(struct ieee80211_tx_rate *rate) {
+  if (!(rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH)) {
+    if (!(rate->flags & IEEE80211_TX_RC_SHORT_GI))
+      return ieee80211n_ht20_gi800[rate->idx];
+
+    return ieee80211n_ht20_gi400[rate->idx];
+  }
+  else {
+    if (!(rate->flags & IEEE80211_TX_RC_SHORT_GI))
+      return ieee80211n_ht40_gi800[rate->idx];
+
+    return ieee80211n_ht40_gi400[rate->idx];
+  }
+}
+
 static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
 {
 	struct ieee80211_sub_if_data *sdata = sta->sdata;
 
 	sinfo->filled = STATION_INFO_INACTIVE_TIME |
 			STATION_INFO_RX_BYTES |
-			STATION_INFO_TX_BYTES;
+			STATION_INFO_TX_BYTES |
+			STATION_INFO_RX_BITRATE |
+			STATION_INFO_TX_BITRATE;
 
 	sinfo->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx);
 	sinfo->rx_bytes = sta->rx_bytes;
 	sinfo->tx_bytes = sta->tx_bytes;
 
+	if (sta->local->hw.flags & IEEE80211_HW_SIGNAL_DBM) {
+		sinfo->filled |= STATION_INFO_SIGNAL;
+		sinfo->signal = sta->last_signal;
+	}
+
+	sinfo->rx_bitrate = sta->last_rxrate_unicast;
+
+	sinfo->tx_bitrate_flags = sta->last_tx_rate.flags &
+	    (IEEE80211_TX_RC_MCS |
+	     IEEE80211_TX_RC_40_MHZ_WIDTH |
+	     IEEE80211_TX_RC_SHORT_GI);
+
+	if (!(sta->last_tx_rate.flags & IEEE80211_TX_RC_MCS)) {
+		struct ieee80211_supported_band *sband;
+		sband = sta->local->hw.wiphy->bands[sta->local->hw.conf.channel->band];
+		sinfo->tx_bitrate = sband->bitrates[sta->last_tx_rate.idx].bitrate;
+		sinfo->tx_bitrate_mcs = 0;
+	}
+	else {
+		sinfo->tx_bitrate = sta_get_80211n_bitrate(&sta->last_tx_rate);
+		sinfo->tx_bitrate_mcs = sta->last_tx_rate.idx;
+	}
+
 	if (ieee80211_vif_is_mesh(&sdata->vif)) {
 #ifdef CONFIG_MAC80211_MESH
 		sinfo->filled |= STATION_INFO_LLID |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 5a1a60f..4b8ee9b 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -720,8 +720,15 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
 	if (rx->sdata->vif.type == NL80211_IFTYPE_ADHOC) {
 		u8 *bssid = ieee80211_get_bssid(hdr, rx->skb->len,
 						NL80211_IFTYPE_ADHOC);
-		if (compare_ether_addr(bssid, rx->sdata->u.sta.bssid) == 0)
+		if (compare_ether_addr(bssid, rx->sdata->u.sta.bssid) == 0) {
 			sta->last_rx = jiffies;
+
+			/* only update last_rxrate_unicast when we receive a
+			 * unicast packet for this station */
+			if (compare_ether_addr(hdr->addr1, sta->sta.addr)) {
+			  sta->last_rxrate_unicast = rx->rate->bitrate;
+			}
+		}
 	} else
 	if (!is_multicast_ether_addr(hdr->addr1) ||
 	    rx->sdata->vif.type == NL80211_IFTYPE_STATION) {
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index dc2606d..d2853ae 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -254,6 +254,7 @@ struct sta_info {
 	int last_signal;
 	int last_qual;
 	int last_noise;
+	u16 last_rxrate_unicast;
 	__le16 last_seq_ctrl[NUM_RX_DATA_QUEUES];
 
 	/* Updated from TX status path only, no locking requirements */
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index c9141e3..1a89409 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -16,6 +16,7 @@
 #include <linux/netlink.h>
 #include <net/genetlink.h>
 #include <net/cfg80211.h>
+#include <net/mac80211.h>
 #include "core.h"
 #include "nl80211.h"
 #include "reg.h"
@@ -1057,7 +1058,24 @@ static int nl80211_send_station(struct sk_buff *msg, 
u32 pid, u32 seq,
 	if (sinfo->filled & STATION_INFO_PLINK_STATE)
 		NLA_PUT_U8(msg, NL80211_STA_INFO_PLINK_STATE,
 			    sinfo->plink_state);
-
+	if (sinfo->filled & STATION_INFO_SIGNAL)
+		NLA_PUT_U8(msg, NL80211_STA_INFO_SIGNAL,
+			    sinfo->signal);
+	if (sinfo->filled & STATION_INFO_RX_BITRATE)
+		NLA_PUT_U16(msg, NL80211_STA_INFO_RX_BITRATE,
+		            sinfo->rx_bitrate);
+	if (sinfo->filled & STATION_INFO_TX_BITRATE) {
+		NLA_PUT_U16(msg, NL80211_STA_INFO_TX_BITRATE,
+		            sinfo->tx_bitrate);
+
+		if (sinfo->tx_bitrate_flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
+			NLA_PUT_FLAG(msg, NL80211_STA_INFO_TX_BITRATE_40_MHZ);
+		if (sinfo->tx_bitrate_flags & IEEE80211_TX_RC_SHORT_GI)
+			NLA_PUT_FLAG(msg, NL80211_STA_INFO_TX_BITRATE_SHORT_GI);
+		if (sinfo->tx_bitrate_flags & IEEE80211_TX_RC_MCS)
+			NLA_PUT_U16(msg, NL80211_STA_INFO_TX_BITRATE_MCS,
+				    sinfo->tx_bitrate_mcs);
+	}
 	nla_nest_end(msg, sinfoattr);
 
 	return genlmsg_end(msg, hdr);


[-- Attachment #1.2: station.c --]
[-- Type: text/x-csrc, Size: 6474 bytes --]

#include <net/if.h>
#include <errno.h>
#include <string.h>

#include <netlink/genl/genl.h>
#include <netlink/genl/family.h>
#include <netlink/genl/ctrl.h>
#include <netlink/msg.h>
#include <netlink/attr.h>

#include "nl80211.h"
#include "iw.h"

enum plink_state {
	LISTEN,
	OPN_SNT,
	OPN_RCVD,
	CNF_RCVD,
	ESTAB,
	HOLDING,
	BLOCKED
};

enum plink_actions {
	PLINK_ACTION_UNDEFINED,
	PLINK_ACTION_OPEN,
	PLINK_ACTION_BLOCK,
};


static int print_sta_handler(struct nl_msg *msg, void *arg)
{
	struct nlattr *tb[NL80211_ATTR_MAX + 1];
	struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
	struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
	char mac_addr[20], state_name[10], dev[20];
	static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
		[NL80211_STA_INFO_INACTIVE_TIME] = { .type = NLA_U32 },
		[NL80211_STA_INFO_RX_BYTES] = { .type = NLA_U32 },
		[NL80211_STA_INFO_TX_BYTES] = { .type = NLA_U32 },
		[NL80211_STA_INFO_LLID] = { .type = NLA_U16 },
		[NL80211_STA_INFO_PLID] = { .type = NLA_U16 },
		[NL80211_STA_INFO_PLINK_STATE] = { .type = NLA_U8 },
		[NL80211_STA_INFO_SIGNAL] = { .type = NLA_U8 },
		[NL80211_STA_INFO_RX_BITRATE] = { .type = NLA_U16 },
		[NL80211_STA_INFO_TX_BITRATE] = { .type = NLA_U16 },
		[NL80211_STA_INFO_TX_BITRATE_40_MHZ] = { .type = NLA_FLAG },
		[NL80211_STA_INFO_TX_BITRATE_SHORT_GI] = { .type = NLA_FLAG },
		[NL80211_STA_INFO_TX_BITRATE_MCS] = { .type = NLA_U8 },
	};

	nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
		  genlmsg_attrlen(gnlh, 0), NULL);

	/*
	 * TODO: validate the interface and mac address!
	 * Otherwise, there's a race condition as soon as
	 * the kernel starts sending station notifications.
	 */

	if (!tb[NL80211_ATTR_STA_INFO]) {
		fprintf(stderr, "sta stats missing!");
		return NL_SKIP;
	}
	if (nla_parse_nested(sinfo, NL80211_STA_INFO_MAX,
			     tb[NL80211_ATTR_STA_INFO],
			     stats_policy)) {
		fprintf(stderr, "failed to parse nested attributes!");
		return NL_SKIP;
	}

	mac_addr_n2a(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
	if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
	printf("Station %s (on %s)", mac_addr, dev);

	if (sinfo[NL80211_STA_INFO_INACTIVE_TIME])
		printf("\n\tinactive time:\t%d ms",
			nla_get_u32(sinfo[NL80211_STA_INFO_INACTIVE_TIME]));
	if (sinfo[NL80211_STA_INFO_RX_BYTES])
		printf("\n\trx bytes:\t%d",
			nla_get_u32(sinfo[NL80211_STA_INFO_RX_BYTES]));
	if (sinfo[NL80211_STA_INFO_TX_BYTES])
		printf("\n\ttx bytes:\t%d",
			nla_get_u32(sinfo[NL80211_STA_INFO_TX_BYTES]));
	if (sinfo[NL80211_STA_INFO_SIGNAL])
		printf("\n\tsignal:  \t%d dBm",
			(int8_t)nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]));
	if (sinfo[NL80211_STA_INFO_RX_BITRATE]) {
		int bitrate = nla_get_u16(sinfo[NL80211_STA_INFO_RX_BITRATE]);
		printf("\n\trx-bitrate:\t%d.%01d MBit/s", bitrate/10, bitrate % 10);
	}
	if (sinfo[NL80211_STA_INFO_TX_BITRATE]) {
		int bitrate = 0;
		int mcs = -1;
		int short_gi = 0;
		
		bitrate = nla_get_u16(sinfo[NL80211_STA_INFO_TX_BITRATE]);
		if (sinfo[NL80211_STA_INFO_TX_BITRATE_MCS])
			mcs = nla_get_u8(sinfo[NL80211_STA_INFO_TX_BITRATE_MCS]);
		if (sinfo[NL80211_STA_INFO_TX_BITRATE_SHORT_GI])
			short_gi = 1;
		
		printf("\n\ttx-bitrate:\t%d.%01d MBit/s", bitrate/10, bitrate % 10);
		if (sinfo[NL80211_STA_INFO_TX_BITRATE_40_MHZ])
			printf(" 40Mhz");
		if (mcs != -1) {
			printf(" (MCS %d%s)", mcs, short_gi ? ", short guard interval" : "");
		}
	}
	if (sinfo[NL80211_STA_INFO_LLID])
		printf("\n\tmesh llid:\t%d",
			nla_get_u16(sinfo[NL80211_STA_INFO_LLID]));
	if (sinfo[NL80211_STA_INFO_PLID])
		printf("\n\tmesh plid:\t%d",
			nla_get_u16(sinfo[NL80211_STA_INFO_PLID]));
	if (sinfo[NL80211_STA_INFO_PLINK_STATE]) {
		switch (nla_get_u16(sinfo[NL80211_STA_INFO_PLINK_STATE])) {
		case LISTEN:
			strcpy(state_name, "LISTEN");
			break;
		case OPN_SNT:
			strcpy(state_name, "OPN_SNT");
			break;
		case OPN_RCVD:
			strcpy(state_name, "OPN_RCVD");
			break;
		case CNF_RCVD:
			strcpy(state_name, "CNF_RCVD");
			break;
		case ESTAB:
			strcpy(state_name, "ESTAB");
			break;
		case HOLDING:
			strcpy(state_name, "HOLDING");
			break;
		case BLOCKED:
			strcpy(state_name, "BLOCKED");
			break;
		default:
			strcpy(state_name, "UNKNOWN");
			break;
		}
		printf("\n\tmesh plink:\t%s", state_name);
	}

	printf("\n");
	return NL_SKIP;
}

static int handle_station_get(struct nl_cb *cb,
			      struct nl_msg *msg,
			      int argc, char **argv)
{
	unsigned char mac_addr[ETH_ALEN];

	if (argc < 1)
		return 1;

	if (mac_addr_a2n(mac_addr, argv[0])) {
		fprintf(stderr, "invalid mac address\n");
		return 2;
	}

	argc--;
	argv++;

	if (argc)
		return 1;

	NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr);

	nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, print_sta_handler, NULL);

	return 0;
 nla_put_failure:
	return -ENOBUFS;
}
COMMAND(station, get, "<MAC address>",
	NL80211_CMD_GET_STATION, 0, CIB_NETDEV, handle_station_get);
COMMAND(station, del, "<MAC address>",
	NL80211_CMD_DEL_STATION, 0, CIB_NETDEV, handle_station_get);

static int handle_station_set(struct nl_cb *cb,
			      struct nl_msg *msg,
			      int argc, char **argv)
{
	unsigned char plink_action;
	unsigned char mac_addr[ETH_ALEN];

	if (argc < 3)
		return 1;

	if (mac_addr_a2n(mac_addr, argv[0])) {
		fprintf(stderr, "invalid mac address\n");
		return 2;
	}
	argc--;
	argv++;

	if (strcmp("plink_action", argv[0]) != 0)
		return 1;
	argc--;
	argv++;

	if (strcmp("open", argv[0]) == 0)
		plink_action = PLINK_ACTION_OPEN;
	else if (strcmp("block", argv[0]) == 0)
		plink_action = PLINK_ACTION_BLOCK;
	else {
		fprintf(stderr, "plink action not supported\n");
		return 2;
	}
	argc--;
	argv++;

	if (argc)
		return 1;

	NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr);
	NLA_PUT_U8(msg, NL80211_ATTR_STA_PLINK_ACTION, plink_action);

	return 0;
 nla_put_failure:
	return -ENOBUFS;
}
COMMAND(station, set, "<MAC address> plink_action <open|block>",
	NL80211_CMD_SET_STATION, 0, CIB_NETDEV, handle_station_set);

static int handle_station_dump(struct nl_cb *cb,
			       struct nl_msg *msg,
			       int argc, char **argv)
{
	nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, print_sta_handler, NULL);
	return 0;
}
COMMAND(station, dump, NULL,
	NL80211_CMD_GET_STATION, NLM_F_DUMP, CIB_NETDEV, handle_station_dump);

[-- Attachment #1.3: nl80211ext_v5.patch --]
[-- Type: text/x-patch, Size: 9969 bytes --]

diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index e08c8bc..32bb7ad 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -404,6 +404,14 @@ enum nl80211_sta_flags {
  * @NL80211_STA_INFO_TX_BYTES: total transmitted bytes (u32, to this station)
  * @__NL80211_STA_INFO_AFTER_LAST: internal
  * @NL80211_STA_INFO_MAX: highest possible station info attribute
+ * @NL80211_STA_INFO_SIGNAL: signal strength of last received package (u8, dBm)
+ * @NL80211_STA_INFO_RX_BITRATE: bitrate of last received unicast packet
+ *  (u16, 100 kbit/s)
+ * @NL80211_STA_INFO_TX_BITRATE: current unicast tx rate (u16, 100 kbit/s)
+ * @NL80211_STA_INFO_TX_BITRATE_40_MHZ: dual channel transmission (flag)
+ * @NL80211_STA_INFO_TX_BITRATE_MCS: 802.11n MCS index of tx rate (u8)
+ * @NL80211_STA_INFO_TX_BITRATE_SHORT_GI: 802.11n with 400ns GI, 800ns
+ *  otherwise, should be ignored if TX_BITRATE_MCS is not set (flag)
  */
 enum nl80211_sta_info {
 	__NL80211_STA_INFO_INVALID,
@@ -413,6 +421,12 @@ enum nl80211_sta_info {
 	NL80211_STA_INFO_LLID,
 	NL80211_STA_INFO_PLID,
 	NL80211_STA_INFO_PLINK_STATE,
+	NL80211_STA_INFO_SIGNAL,
+	NL80211_STA_INFO_RX_BITRATE,
+	NL80211_STA_INFO_TX_BITRATE,
+	NL80211_STA_INFO_TX_BITRATE_40_MHZ,
+	NL80211_STA_INFO_TX_BITRATE_MCS,
+	NL80211_STA_INFO_TX_BITRATE_SHORT_GI,
 
 	/* keep last */
 	__NL80211_STA_INFO_AFTER_LAST,
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 1d57835..5cc8b53 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -160,6 +160,8 @@ struct station_parameters {
  *
  * Used by the driver to indicate which info in &struct station_info
  * it has filled in during get_station() or dump_station().
+ * Signal strength is only available if driver supports dBm signal
+ * strength.
  *
  * @STATION_INFO_INACTIVE_TIME: @inactive_time filled
  * @STATION_INFO_RX_BYTES: @rx_bytes filled
@@ -167,6 +169,10 @@ struct station_parameters {
  * @STATION_INFO_LLID: @llid filled
  * @STATION_INFO_PLID: @plid filled
  * @STATION_INFO_PLINK_STATE: @plink_state filled
+ * @STATION_INFO_SIGNAL: @signal filled
+ * @STATION_INFO_RX_BITRATE: @rx_bitrate filled
+ * @STATION_INFO_TX_BITRATE: @tx_bitrate fields are filled
+ *  (tx_bitrate, tx_bitrate_flags and tx_bitrate_mcs)
  */
 enum station_info_flags {
 	STATION_INFO_INACTIVE_TIME	= 1<<0,
@@ -175,6 +181,9 @@ enum station_info_flags {
 	STATION_INFO_LLID		= 1<<3,
 	STATION_INFO_PLID		= 1<<4,
 	STATION_INFO_PLINK_STATE	= 1<<5,
+	STATION_INFO_SIGNAL		= 1<<6,
+	STATION_INFO_RX_BITRATE		= 1<<7,
+	STATION_INFO_TX_BITRATE		= 1<<8,
 };
 
 /**
@@ -189,6 +198,15 @@ enum station_info_flags {
  * @llid: mesh local link id
  * @plid: mesh peer link id
  * @plink_state: mesh peer link state
+ * @signal: signal strength of last received package in dBm
+ * @rx_bitrate: bitrate of last received unicast packet in 100 kbit/sec
+ * @tx_bitrate: current unicast bitrate to this station in 100 kbit/sec
+ * @tx_bitrate_flags: a binary field with a combination of flags
+ *  IEEE80211_TX_RC_MCS: bitrate_mcs field contains the 802.11n MCS number
+ *  IEEE80211_TX_RC_40_MHZ_WIDTH: 40 Mhz wide channel, 20 Mhz if not set
+ *  IEEE80211_TX_RC_SHORT_GI: 400ns guard interval, 800ns if not set
+ * @tx_bitrate_mcs: if IEEE80211_TX_RC_MCS is set this is the MCS index
+ *  of a 802.11n transmission, if not it is set to zero
  */
 struct station_info {
 	u32 filled;
@@ -198,6 +216,10 @@ struct station_info {
 	u16 llid;
 	u16 plid;
 	u8 plink_state;
+	u8 signal;
+	u16 rx_bitrate;
+	u16 tx_bitrate;
+	u8 tx_bitrate_flags, tx_bitrate_mcs;
 };
 
 /**
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 16423f9..dc684a4 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -17,6 +17,41 @@
 #include "rate.h"
 #include "mesh.h"
 
+/* bitrate of 802.11n ht20 connections with 800ns guard interval in 100kbit/s */
+const u16 ieee80211n_ht20_gi800[] = {
+    65, 130, 195, 260, 390, 520, 585, 650,
+    130, 260, 390, 520, 780, 1040, 1170, 1300,
+    195, 390, 585, 780, 1170, 1560, 1755, 1950,
+    260, 520, 780, 1040, 1560, 2080, 2340, 2600
+};
+
+/* bitrate of 802.11n ht20 connections with 400ns guard interval
+ * in 100kbit/s per spatial stream */
+const u16 ieee80211n_ht20_gi400[] = {
+    72, 144, 217, 289, 433, 578, 650, 722,
+    144, 289, 433, 578, 867, 1156, 1300, 1440,
+    217, 433, 650, 867, 1300, 1733, 1950, 2167,
+    289, 578, 867, 1157, 1733, 2311, 2600, 2889
+};
+
+/* bitrate of 802.11n ht40 connections with 800ns guard interval
+ * in 100kbit/s per spatial stream */
+const u16 ieee80211n_ht40_gi800[] = {
+    135, 270, 405, 540, 810, 1080, 1215, 1350,
+    270, 540, 810, 1080, 1620, 2160, 2430, 2700,
+    405, 810, 1215, 1620, 2430, 3240, 3645, 4050,
+    540, 1080, 1620, 2160, 3240, 4320, 4860, 5400
+};
+
+/* bitrate of 802.11n ht40 connections with 400ns guard interval
+ * in 100kbit/s per spatial stream */
+const u16 ieee80211n_ht40_gi400[] = {
+    150, 300, 450, 600, 900, 1200, 1350, 1500,
+    300, 600, 900, 1200, 1800, 2400, 2700, 3000,
+    450, 900, 1350, 1800, 2700, 3600, 4050, 4500,
+    600, 1200, 1800, 2400, 3600, 4800, 5400, 6000
+};
+
 static bool nl80211_type_check(enum nl80211_iftype type)
 {
 	switch (type) {
@@ -304,18 +339,58 @@ static int ieee80211_config_default_key(struct wiphy *wiphy,
 	return 0;
 }
 
+static u16 sta_get_80211n_bitrate(struct ieee80211_tx_rate *rate) {
+  if (!(rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH)) {
+    if (!(rate->flags & IEEE80211_TX_RC_SHORT_GI))
+      return ieee80211n_ht20_gi800[rate->idx];
+
+    return ieee80211n_ht20_gi400[rate->idx];
+  }
+  else {
+    if (!(rate->flags & IEEE80211_TX_RC_SHORT_GI))
+      return ieee80211n_ht40_gi800[rate->idx];
+
+    return ieee80211n_ht40_gi400[rate->idx];
+  }
+}
+
 static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
 {
 	struct ieee80211_sub_if_data *sdata = sta->sdata;
 
 	sinfo->filled = STATION_INFO_INACTIVE_TIME |
 			STATION_INFO_RX_BYTES |
-			STATION_INFO_TX_BYTES;
+			STATION_INFO_TX_BYTES |
+			STATION_INFO_RX_BITRATE |
+			STATION_INFO_TX_BITRATE;
 
 	sinfo->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx);
 	sinfo->rx_bytes = sta->rx_bytes;
 	sinfo->tx_bytes = sta->tx_bytes;
 
+	if (sta->local->hw.flags & IEEE80211_HW_SIGNAL_DBM) {
+		sinfo->filled |= STATION_INFO_SIGNAL;
+		sinfo->signal = sta->last_signal;
+	}
+
+	sinfo->rx_bitrate = sta->last_rxrate_unicast;
+
+	sinfo->tx_bitrate_flags = sta->last_tx_rate.flags &
+	    (IEEE80211_TX_RC_MCS |
+	     IEEE80211_TX_RC_40_MHZ_WIDTH |
+	     IEEE80211_TX_RC_SHORT_GI);
+
+	if (!(sta->last_tx_rate.flags & IEEE80211_TX_RC_MCS)) {
+		struct ieee80211_supported_band *sband;
+		sband = sta->local->hw.wiphy->bands[sta->local->hw.conf.channel->band];
+		sinfo->tx_bitrate = sband->bitrates[sta->last_tx_rate.idx].bitrate;
+		sinfo->tx_bitrate_mcs = 0;
+	}
+	else {
+		sinfo->tx_bitrate = sta_get_80211n_bitrate(&sta->last_tx_rate);
+		sinfo->tx_bitrate_mcs = sta->last_tx_rate.idx;
+	}
+
 	if (ieee80211_vif_is_mesh(&sdata->vif)) {
 #ifdef CONFIG_MAC80211_MESH
 		sinfo->filled |= STATION_INFO_LLID |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 5a1a60f..4b8ee9b 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -720,8 +720,15 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
 	if (rx->sdata->vif.type == NL80211_IFTYPE_ADHOC) {
 		u8 *bssid = ieee80211_get_bssid(hdr, rx->skb->len,
 						NL80211_IFTYPE_ADHOC);
-		if (compare_ether_addr(bssid, rx->sdata->u.sta.bssid) == 0)
+		if (compare_ether_addr(bssid, rx->sdata->u.sta.bssid) == 0) {
 			sta->last_rx = jiffies;
+
+			/* only update last_rxrate_unicast when we receive a
+			 * unicast packet for this station */
+			if (compare_ether_addr(hdr->addr1, sta->sta.addr)) {
+			  sta->last_rxrate_unicast = rx->rate->bitrate;
+			}
+		}
 	} else
 	if (!is_multicast_ether_addr(hdr->addr1) ||
 	    rx->sdata->vif.type == NL80211_IFTYPE_STATION) {
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index dc2606d..d2853ae 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -254,6 +254,7 @@ struct sta_info {
 	int last_signal;
 	int last_qual;
 	int last_noise;
+	u16 last_rxrate_unicast;
 	__le16 last_seq_ctrl[NUM_RX_DATA_QUEUES];
 
 	/* Updated from TX status path only, no locking requirements */
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index c9141e3..1a89409 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -16,6 +16,7 @@
 #include <linux/netlink.h>
 #include <net/genetlink.h>
 #include <net/cfg80211.h>
+#include <net/mac80211.h>
 #include "core.h"
 #include "nl80211.h"
 #include "reg.h"
@@ -1057,7 +1058,24 @@ static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
 	if (sinfo->filled & STATION_INFO_PLINK_STATE)
 		NLA_PUT_U8(msg, NL80211_STA_INFO_PLINK_STATE,
 			    sinfo->plink_state);
-
+	if (sinfo->filled & STATION_INFO_SIGNAL)
+		NLA_PUT_U8(msg, NL80211_STA_INFO_SIGNAL,
+			    sinfo->signal);
+	if (sinfo->filled & STATION_INFO_RX_BITRATE)
+		NLA_PUT_U16(msg, NL80211_STA_INFO_RX_BITRATE,
+		            sinfo->rx_bitrate);
+	if (sinfo->filled & STATION_INFO_TX_BITRATE) {
+		NLA_PUT_U16(msg, NL80211_STA_INFO_TX_BITRATE,
+		            sinfo->tx_bitrate);
+
+		if (sinfo->tx_bitrate_flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
+			NLA_PUT_FLAG(msg, NL80211_STA_INFO_TX_BITRATE_40_MHZ);
+		if (sinfo->tx_bitrate_flags & IEEE80211_TX_RC_SHORT_GI)
+			NLA_PUT_FLAG(msg, NL80211_STA_INFO_TX_BITRATE_SHORT_GI);
+		if (sinfo->tx_bitrate_flags & IEEE80211_TX_RC_MCS)
+			NLA_PUT_U16(msg, NL80211_STA_INFO_TX_BITRATE_MCS,
+				    sinfo->tx_bitrate_mcs);
+	}
 	nla_nest_end(msg, sinfoattr);
 
 	return genlmsg_end(msg, hdr);

[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 197 bytes --]

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

* Re: RFC Patch v2: Add signal strength to nl80211station info
  2008-12-03 10:31                     ` Henning Rogge
@ 2008-12-04  8:47                       ` Johannes Berg
  2008-12-04  9:48                         ` Henning Rogge
  2008-12-04 20:26                       ` Johannes Berg
  1 sibling, 1 reply; 66+ messages in thread
From: Johannes Berg @ 2008-12-04  8:47 UTC (permalink / raw)
  To: Henning Rogge
  Cc: Luis R. Rodriguez, Henning Rogge, Luis Rodriguez,
	Marcel Holtmann, linux-wireless, nbd

On Wed, 2008-12-03 at 11:31 +0100, Henning Rogge wrote:

> What do you think about the idea to export the 802.11n transmission rate 
> through the old WExt interface, so iwconfig will show the correct rate too ? 
> But for this the "mcs to bitrate" tables would have to be moved to some other 
> file, so wext.c can access them too (which one ?).

No, that can't possibly work right, sorry.

> + * @NL80211_STA_INFO_SIGNAL: signal strength of last received package (u8, 
> dBm)

s8? should be signed, no?

> + * @NL80211_STA_INFO_RX_BITRATE: bitrate of last received unicast packet
> + *  (u16, 100 kbit/s)

I don't really like this. I know we cannot report the real information
yet because we don't even have the driver/mac80211 api but let's add rx
rate reporting when we have the HT information too.

> + * @NL80211_STA_INFO_TX_BITRATE: current unicast tx rate (u16, 100 kbit/s)
> + * @NL80211_STA_INFO_TX_BITRATE_40_MHZ: dual channel transmission (flag)
> + * @NL80211_STA_INFO_TX_BITRATE_MCS: 802.11n MCS index of tx rate (u8)
> + * @NL80211_STA_INFO_TX_BITRATE_SHORT_GI: 802.11n with 400ns GI, 800ns
> + *  otherwise, should be ignored if TX_BITRATE_MCS is not set (flag)

I'm not sure I like the bitrate being used as prefix and final name, can
we have maybe TXRATE_ as prefix and use TXRATE_RATE, TXRATE_40, ...?

> +/* bitrate of 802.11n ht20 connections with 800ns guard interval in 100kbit/s 
> */
> +const u16 ieee80211n_ht20_gi800[] = {
> +    65, 130, 195, 260, 390, 520, 585, 650,
> +    130, 260, 390, 520, 780, 1040, 1170, 1300,
> +    195, 390, 585, 780, 1170, 1560, 1755, 1950,
> +    260, 520, 780, 1040, 1560, 2080, 2340, 2600
> +};
> +
> +/* bitrate of 802.11n ht20 connections with 400ns guard interval
> + * in 100kbit/s per spatial stream */
> +const u16 ieee80211n_ht20_gi400[] = {
> +    72, 144, 217, 289, 433, 578, 650, 722,
> +    144, 289, 433, 578, 867, 1156, 1300, 1440,
> +    217, 433, 650, 867, 1300, 1733, 1950, 2167,
> +    289, 578, 867, 1157, 1733, 2311, 2600, 2889
> +};
> +
> +/* bitrate of 802.11n ht40 connections with 800ns guard interval
> + * in 100kbit/s per spatial stream */
> +const u16 ieee80211n_ht40_gi800[] = {
> +    135, 270, 405, 540, 810, 1080, 1215, 1350,
> +    270, 540, 810, 1080, 1620, 2160, 2430, 2700,
> +    405, 810, 1215, 1620, 2430, 3240, 3645, 4050,
> +    540, 1080, 1620, 2160, 3240, 4320, 4860, 5400
> +};
> +
> +/* bitrate of 802.11n ht40 connections with 400ns guard interval
> + * in 100kbit/s per spatial stream */
> +const u16 ieee80211n_ht40_gi400[] = {
> +    150, 300, 450, 600, 900, 1200, 1350, 1500,
> +    300, 600, 900, 1200, 1800, 2400, 2700, 3000,
> +    450, 900, 1350, 1800, 2700, 3600, 4050, 4500,
> +    600, 1200, 1800, 2400, 3600, 4800, 5400, 6000
> +};

I definitely don't like this, ick, please put that into userspace.

> +	if (sta->local->hw.flags & IEEE80211_HW_SIGNAL_DBM) {
> +		sinfo->filled |= STATION_INFO_SIGNAL;
> +		sinfo->signal = sta->last_signal;
> +	}

Good plan to report only when dBm are available, I like that.

> +	sinfo->rx_bitrate = sta->last_rxrate_unicast;
> +
> +	sinfo->tx_bitrate_flags = sta->last_tx_rate.flags &
> +	    (IEEE80211_TX_RC_MCS |
> +	     IEEE80211_TX_RC_40_MHZ_WIDTH |
> +	     IEEE80211_TX_RC_SHORT_GI);

That looks very odd. Are you sure it's using the same rate flags? And if
it is, that's wrong, because cfg80211 must not rely on mac80211 flags.

> +	if (!(sta->last_tx_rate.flags & IEEE80211_TX_RC_MCS)) {
> +		struct ieee80211_supported_band *sband;
> +		sband = sta->local->hw.wiphy->bands[sta->local->hw.conf.channel->band];
> +		sinfo->tx_bitrate = sband->bitrates[sta->last_tx_rate.idx].bitrate;
> +		sinfo->tx_bitrate_mcs = 0;

I don't think you should initialise mcs here.

Some places also need work on the coding style.

johannes


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

* Re: RFC Patch v2: Add signal strength to nl80211station info
  2008-12-04  8:47                       ` Johannes Berg
@ 2008-12-04  9:48                         ` Henning Rogge
  2008-12-04 13:02                           ` Johannes Berg
  0 siblings, 1 reply; 66+ messages in thread
From: Henning Rogge @ 2008-12-04  9:48 UTC (permalink / raw)
  To: Johannes Berg
  Cc: Luis R. Rodriguez, Henning Rogge, Luis Rodriguez,
	Marcel Holtmann, linux-wireless, nbd

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

Am Thursday 04 December 2008 09:47:52 schrieb Johannes Berg:
> On Wed, 2008-12-03 at 11:31 +0100, Henning Rogge wrote:
> > What do you think about the idea to export the 802.11n transmission rate
> > through the old WExt interface, so iwconfig will show the correct rate
> > too ? But for this the "mcs to bitrate" tables would have to be moved to
> > some other file, so wext.c can access them too (which one ?).
>
> No, that can't possibly work right, sorry.
I think it would work for reading the bitrate with WExt, but not for setting 
the bitrate.

> > + * @NL80211_STA_INFO_SIGNAL: signal strength of last received package
> > (u8, dBm)
>
> s8? should be signed, no?
Yes, it should be signed, but nl80211 does not support signed values. Shall I 
document it as signed but use the unsigned macros to transmit it through 
nl80211 to userspace (not sure about it) ?

> > + * @NL80211_STA_INFO_RX_BITRATE: bitrate of last received unicast packet
> > + *  (u16, 100 kbit/s)
>
> I don't really like this. I know we cannot report the real information
> yet because we don't even have the driver/mac80211 api but let's add rx
> rate reporting when we have the HT information too.
I'm not sure I understand your problem.

We have the mcs number from the driver, we have the the 20/40 Mhz flag and we 
have to 400/800ns guard interval flag. That should be everything we need.

> > + * @NL80211_STA_INFO_TX_BITRATE: current unicast tx rate (u16, 100
> > kbit/s) + * @NL80211_STA_INFO_TX_BITRATE_40_MHZ: dual channel
> > transmission (flag) + * @NL80211_STA_INFO_TX_BITRATE_MCS: 802.11n MCS
> > index of tx rate (u8) + * @NL80211_STA_INFO_TX_BITRATE_SHORT_GI: 802.11n
> > with 400ns GI, 800ns + *  otherwise, should be ignored if TX_BITRATE_MCS
> > is not set (flag)
>
> I'm not sure I like the bitrate being used as prefix and final name, can
> we have maybe TXRATE_ as prefix and use TXRATE_RATE, TXRATE_40, ...?
Like this ?

NL80211_STA_INFO_TXRATE_RATE
NL80211_STA_INFO_TXRATE_40_MHZ
NL80211_STA_INFO_TXRATE_MCS
NL80211_STA_INFO_TXRATE_SHORT_GI

> > +/* bitrate of 802.11n ht20 connections with 800ns guard interval in
> > 100kbit/s */
> > +const u16 ieee80211n_ht20_gi800[] = {
> > +    65, 130, 195, 260, 390, 520, 585, 650,
> > +    130, 260, 390, 520, 780, 1040, 1170, 1300,
> > +    195, 390, 585, 780, 1170, 1560, 1755, 1950,
> > +    260, 520, 780, 1040, 1560, 2080, 2340, 2600
> > +};
> > +
> > +/* bitrate of 802.11n ht20 connections with 400ns guard interval
> > + * in 100kbit/s per spatial stream */
> > +const u16 ieee80211n_ht20_gi400[] = {
> > +    72, 144, 217, 289, 433, 578, 650, 722,
> > +    144, 289, 433, 578, 867, 1156, 1300, 1440,
> > +    217, 433, 650, 867, 1300, 1733, 1950, 2167,
> > +    289, 578, 867, 1157, 1733, 2311, 2600, 2889
> > +};
> > +
> > +/* bitrate of 802.11n ht40 connections with 800ns guard interval
> > + * in 100kbit/s per spatial stream */
> > +const u16 ieee80211n_ht40_gi800[] = {
> > +    135, 270, 405, 540, 810, 1080, 1215, 1350,
> > +    270, 540, 810, 1080, 1620, 2160, 2430, 2700,
> > +    405, 810, 1215, 1620, 2430, 3240, 3645, 4050,
> > +    540, 1080, 1620, 2160, 3240, 4320, 4860, 5400
> > +};
> > +
> > +/* bitrate of 802.11n ht40 connections with 400ns guard interval
> > + * in 100kbit/s per spatial stream */
> > +const u16 ieee80211n_ht40_gi400[] = {
> > +    150, 300, 450, 600, 900, 1200, 1350, 1500,
> > +    300, 600, 900, 1200, 1800, 2400, 2700, 3000,
> > +    450, 900, 1350, 1800, 2700, 3600, 4050, 4500,
> > +    600, 1200, 1800, 2400, 3600, 4800, 5400, 6000
> > +};
>
> I definitely don't like this, ick, please put that into userspace.
Is there some kind of userspace library I could put this function into ?
Every userspace programm using nl80211 will need this translation function, so 
it would be bad to put it into the iw command.

> > +	sinfo->rx_bitrate = sta->last_rxrate_unicast;
> > +
> > +	sinfo->tx_bitrate_flags = sta->last_tx_rate.flags &
> > +	    (IEEE80211_TX_RC_MCS |
> > +	     IEEE80211_TX_RC_40_MHZ_WIDTH |
> > +	     IEEE80211_TX_RC_SHORT_GI);
>
> That looks very odd. Are you sure it's using the same rate flags? And if
> it is, that's wrong, because cfg80211 must not rely on mac80211 flags.
I just store them in the flags field and translate them into NL80211 flags 
later. They never leave the kernel.

But I can add a new enum for this. Maybe this way ?

enum station_info_txrate_flags {
    STATION_INFO_TXFLAGS_MCS,
    STATION_INFO_TXFLAGS_40_MHZ,
    STATION_INFO_TXFLAGS_SHORT_GI
};

> > +	if (!(sta->last_tx_rate.flags & IEEE80211_TX_RC_MCS)) {
> > +		struct ieee80211_supported_band *sband;
> > +		sband =
> > sta->local->hw.wiphy->bands[sta->local->hw.conf.channel->band];
> > +		sinfo->tx_bitrate = sband->bitrates[sta->last_tx_rate.idx].bitrate;
> > +		sinfo->tx_bitrate_mcs = 0;
> I don't think you should initialise mcs here.
I didn't liked to keep it uninitialized, but I can just delete the line.

> Some places also need work on the coding style.
Maybe you can give me an example, I'm still trying to learn the coding style 
for this group.

Henning

*************************************************
Diplom Informatiker Henning Rogge
Forschungsgesellschaft für
Angewandte Naturwissenschaften e. V. (FGAN) 
Neuenahrer Str. 20, 53343 Wachtberg, Germany
Tel.: 0049 (0)228 9435-961
Fax: 0049 (0)228 9435-685
E-Mail: rogge@fgan.de
Web: www.fgan.de
************************************************
Sitz der Gesellschaft: Bonn
Registergericht: Amtsgericht Bonn VR 2530
Vorstand: Dr. rer. nat. Ralf Dornhaus (Vors.), Prof. Dr. Joachim Ender 
(Stellv.)


[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 197 bytes --]

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

* Re: RFC Patch v2: Add signal strength to nl80211station info
  2008-12-04  9:48                         ` Henning Rogge
@ 2008-12-04 13:02                           ` Johannes Berg
  0 siblings, 0 replies; 66+ messages in thread
From: Johannes Berg @ 2008-12-04 13:02 UTC (permalink / raw)
  To: Henning Rogge
  Cc: Luis R. Rodriguez, Henning Rogge, Luis Rodriguez,
	Marcel Holtmann, linux-wireless, nbd



>> No, that can't possibly work right, sorry.

> I think it would work for reading the bitrate with WExt, but not for
> setting the bitrate.

Yes, that might work, but would be quite inconsistent, IMHO.

>> > + * @NL80211_STA_INFO_SIGNAL: signal strength of last received package
>> > (u8, dBm)
>>
>> s8? should be signed, no?
> Yes, it should be signed, but nl80211 does not support signed values.
> Shall I 
> document it as signed but use the unsigned macros to transmit it through 
> nl80211 to userspace (not sure about it) ?

Yes, please document as signed.

>> > + * @NL80211_STA_INFO_RX_BITRATE: bitrate of last received unicast
> packet
>> > + *  (u16, 100 kbit/s)
>>
>> I don't really like this. I know we cannot report the real information
>> yet because we don't even have the driver/mac80211 api but let's add rx
>> rate reporting when we have the HT information too.

> I'm not sure I understand your problem.

> We have the mcs number from the driver, we have the the 20/40 Mhz flag
and
> we 
> have to 400/800ns guard interval flag. That should be everything we need.

I don't think we have MCS number, where did you see it? And we don't have
the 20/40, GI etc. either, afaict. Remember this is RX.

>> > + * @NL80211_STA_INFO_TX_BITRATE: current unicast tx rate (u16, 100
>> > kbit/s) + * @NL80211_STA_INFO_TX_BITRATE_40_MHZ: dual channel
>> > transmission (flag) + * @NL80211_STA_INFO_TX_BITRATE_MCS: 802.11n MCS
>> > index of tx rate (u8) + * @NL80211_STA_INFO_TX_BITRATE_SHORT_GI:
> 802.11n
>> > with 400ns GI, 800ns + *  otherwise, should be ignored if
> TX_BITRATE_MCS
>> > is not set (flag)
>>
>> I'm not sure I like the bitrate being used as prefix and final name, can
>> we have maybe TXRATE_ as prefix and use TXRATE_RATE, TXRATE_40, ...?
> Like this ?
> 
> NL80211_STA_INFO_TXRATE_RATE
> NL80211_STA_INFO_TXRATE_40_MHZ
> NL80211_STA_INFO_TXRATE_MCS
> NL80211_STA_INFO_TXRATE_SHORT_GI

Yeah, much better.


>> I definitely don't like this, ick, please put that into userspace.
> Is there some kind of userspace library I could put this function into ?
> Every userspace programm using nl80211 will need this translation
> function, so it would be bad to put it into the iw command.

Why would that be bad? Most programs using nl80211 won't care, and this is
fixed information, not something that changes.

>> > +	sinfo->rx_bitrate = sta->last_rxrate_unicast;
>> > +
>> > +	sinfo->tx_bitrate_flags = sta->last_tx_rate.flags &
>> > +	    (IEEE80211_TX_RC_MCS |
>> > +	     IEEE80211_TX_RC_40_MHZ_WIDTH |
>> > +	     IEEE80211_TX_RC_SHORT_GI);
>>
>> That looks very odd. Are you sure it's using the same rate flags? And if
>> it is, that's wrong, because cfg80211 must not rely on mac80211 flags.
> I just store them in the flags field and translate them into NL80211
flags
> 
> later. They never leave the kernel.
> 
> But I can add a new enum for this. Maybe this way ?
> 
> enum station_info_txrate_flags {
>     STATION_INFO_TXFLAGS_MCS,
>     STATION_INFO_TXFLAGS_40_MHZ,
>     STATION_INFO_TXFLAGS_SHORT_GI
> };

Yes, that would be better, and that needs to be defined in cfg80211.

>> > +	if (!(sta->last_tx_rate.flags & IEEE80211_TX_RC_MCS)) {
>> > +		struct ieee80211_supported_band *sband;
>> > +		sband =
>> > sta->local->hw.wiphy->bands[sta->local->hw.conf.channel->band];
>> > +		sinfo->tx_bitrate = sband->bitrates[sta->last_tx_rate.idx].bitrate;
>> > +		sinfo->tx_bitrate_mcs = 0;
>> I don't think you should initialise mcs here.

> I didn't liked to keep it uninitialized, but I can just delete the line.

But it won't be used anyway, so imho it's easier to understand if you
remove it.

>> Some places also need work on the coding style.

> Maybe you can give me an example, I'm still trying to learn the coding
> style for this group.

You can find stuff on that in the Documentation/ directory.

johannes

PS: Sent from new webmail, apologies for the previous johannes@localhost,
let me know if this is ok!

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

* Re: RFC Patch v2: Add signal strength to nl80211station info
  2008-12-03 10:31                     ` Henning Rogge
  2008-12-04  8:47                       ` Johannes Berg
@ 2008-12-04 20:26                       ` Johannes Berg
  2008-12-04 21:12                         ` Luis R. Rodriguez
  1 sibling, 1 reply; 66+ messages in thread
From: Johannes Berg @ 2008-12-04 20:26 UTC (permalink / raw)
  To: Henning Rogge
  Cc: Luis R. Rodriguez, Henning Rogge, Luis Rodriguez,
	Marcel Holtmann, linux-wireless, nbd

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

On Wed, 2008-12-03 at 11:31 +0100, Henning Rogge wrote:

> Changes since v3:
> - added rx_bitrate to station info and sta_info
> - remember bitrate of last received unicast packet to this station

Please remove the RX bitrate for now, the drivers are not currently
reporting HT information appropriately.

> - decode 802.11n MCS index for nl80211
>   (maybe this should be ported to WEXT too ?)

I don't like all the tables in the kernel, please move those to
userspace. If we used more accurate values (these rates are fractional)
then we also don't need the values for the number of streams since those
are perfect multiples (1x, 2x, 3x, 4x for up to 4 streams).

> Changes since v4:
> - added tx_bitrate_flags adn tx_bitrate_mcs field to station info
> - added flags for 40Mhz and small guard interval to NL80211 station info
> - added mcs field to NL80211 station info
> 
> The IEEE80211_TX_RC_40_MHZ_WIDTH flag in nl80211 should work for 802.11g 
> "turbomodes"

I don't think we should ever go there. But that's just me maybe.

> + * @NL80211_STA_INFO_SIGNAL: signal strength of last received package (u8, 
> dBm)
> + * @NL80211_STA_INFO_RX_BITRATE: bitrate of last received unicast packet
> + *  (u16, 100 kbit/s)
> + * @NL80211_STA_INFO_TX_BITRATE: current unicast tx rate (u16, 100 kbit/s)
> + * @NL80211_STA_INFO_TX_BITRATE_40_MHZ: dual channel transmission (flag)
> + * @NL80211_STA_INFO_TX_BITRATE_MCS: 802.11n MCS index of tx rate (u8)
> + * @NL80211_STA_INFO_TX_BITRATE_SHORT_GI: 802.11n with 400ns GI, 800ns
> + *  otherwise, should be ignored if TX_BITRATE_MCS is not set (flag)
>   */
>  enum nl80211_sta_info {
>  	__NL80211_STA_INFO_INVALID,
> @@ -413,6 +421,12 @@ enum nl80211_sta_info {
>  	NL80211_STA_INFO_LLID,
>  	NL80211_STA_INFO_PLID,
>  	NL80211_STA_INFO_PLINK_STATE,
> +	NL80211_STA_INFO_SIGNAL,
> +	NL80211_STA_INFO_RX_BITRATE,
> +	NL80211_STA_INFO_TX_BITRATE,
> +	NL80211_STA_INFO_TX_BITRATE_40_MHZ,
> +	NL80211_STA_INFO_TX_BITRATE_MCS,
> +	NL80211_STA_INFO_TX_BITRATE_SHORT_GI,

Just had another idea. Since we'll end up duplicating these for TX and
RX (ultimately we'll need RX_BITRATE_40_MHZ/MCS/SGI etc too) we should
actually do this differently:

 1) define NL80211_STA_INFO_RATE,
 2) define NL80211_RATE_INFO_BITRATE/40/MCS/SGI

and then nest the bitrate information into the STA_INFO_RATE, just like
station flags are nested etc. That way the RATE_INFO things could also
be used elsewhere.
 
>   * Used by the driver to indicate which info in &struct station_info
>   * it has filled in during get_station() or dump_station().
> + * Signal strength is only available if driver supports dBm signal
> + * strength.

That comment is wrong here since cfg80211 drivers are expected to fill
this correctly. This comment is about _mac80211_ drivers and thus
inappropriate in cfg80211.h.

> + * @signal: signal strength of last received package in dBm

packet, or better yet PPDU

> + * @rx_bitrate: bitrate of last received unicast packet in 100 kbit/sec
> + * @tx_bitrate: current unicast bitrate to this station in 100 kbit/sec
> + * @tx_bitrate_flags: a binary field with a combination of flags
> + *  IEEE80211_TX_RC_MCS: bitrate_mcs field contains the 802.11n MCS number
> + *  IEEE80211_TX_RC_40_MHZ_WIDTH: 40 Mhz wide channel, 20 Mhz if not set
> + *  IEEE80211_TX_RC_SHORT_GI: 400ns guard interval, 800ns if not set

make those tx/rx independent too please, maybe even introduce a new
struct here so that it gets

station_info.tx_rate.flags and eventually .rx_rate.flags too

johannes

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

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

* Re: RFC Patch v2: Add signal strength to nl80211station info
  2008-12-04 20:26                       ` Johannes Berg
@ 2008-12-04 21:12                         ` Luis R. Rodriguez
  2008-12-04 21:20                           ` Johannes Berg
  0 siblings, 1 reply; 66+ messages in thread
From: Luis R. Rodriguez @ 2008-12-04 21:12 UTC (permalink / raw)
  To: Johannes Berg
  Cc: Henning Rogge, Luis Rodriguez, Henning Rogge, Marcel Holtmann,
	linux-wireless, nbd

On Thu, Dec 04, 2008 at 12:26:27PM -0800, Johannes Berg wrote:
> On Wed, 2008-12-03 at 11:31 +0100, Henning Rogge wrote:
> 
> > Changes since v3:
> > - added rx_bitrate to station info and sta_info
> > - remember bitrate of last received unicast packet to this station
> 
> Please remove the RX bitrate for now, the drivers are not currently
> reporting HT information appropriately.

It seems that's the case for ath9k, at least Jouni had pointed out to me.

> > - decode 802.11n MCS index for nl80211
> >   (maybe this should be ported to WEXT too ?)
> 
> I don't like all the tables in the kernel, please move those to
> userspace. If we used more accurate values (these rates are fractional)

So the rate stuff in the 11n wiki page is rounded up, so yeah it would
technically be a bit off so its technically better to let us figure it
out in userspace.. sorry about that Henning... And Johannes also pointed
out to me we actually do have duplicate rates, I failed to catch them.

> then we also don't need the values for the number of streams since those
> are perfect multiples (1x, 2x, 3x, 4x for up to 4 streams).

Well if you have the MCS index and HT mode you get the # of streams. Not
sure I understood the perfect multiple stuff.

> > Changes since v4:
> > - added tx_bitrate_flags adn tx_bitrate_mcs field to station info
> > - added flags for 40Mhz and small guard interval to NL80211 station info
> > - added mcs field to NL80211 station info
> > 
> > The IEEE80211_TX_RC_40_MHZ_WIDTH flag in nl80211 should work for 802.11g 
> > "turbomodes"
> 
> I don't think we should ever go there. But that's just me maybe.

I don't think we want to support this either and I doubt bug reports
for it would get attention from us.

> > + * @NL80211_STA_INFO_SIGNAL: signal strength of last received package (u8, 
> > dBm)
> > + * @NL80211_STA_INFO_RX_BITRATE: bitrate of last received unicast packet
> > + *  (u16, 100 kbit/s)
> > + * @NL80211_STA_INFO_TX_BITRATE: current unicast tx rate (u16, 100 kbit/s)
> > + * @NL80211_STA_INFO_TX_BITRATE_40_MHZ: dual channel transmission (flag)
> > + * @NL80211_STA_INFO_TX_BITRATE_MCS: 802.11n MCS index of tx rate (u8)
> > + * @NL80211_STA_INFO_TX_BITRATE_SHORT_GI: 802.11n with 400ns GI, 800ns
> > + *  otherwise, should be ignored if TX_BITRATE_MCS is not set (flag)
> >   */
> >  enum nl80211_sta_info {
> >  	__NL80211_STA_INFO_INVALID,
> > @@ -413,6 +421,12 @@ enum nl80211_sta_info {
> >  	NL80211_STA_INFO_LLID,
> >  	NL80211_STA_INFO_PLID,
> >  	NL80211_STA_INFO_PLINK_STATE,
> > +	NL80211_STA_INFO_SIGNAL,
> > +	NL80211_STA_INFO_RX_BITRATE,
> > +	NL80211_STA_INFO_TX_BITRATE,
> > +	NL80211_STA_INFO_TX_BITRATE_40_MHZ,
> > +	NL80211_STA_INFO_TX_BITRATE_MCS,
> > +	NL80211_STA_INFO_TX_BITRATE_SHORT_GI,
> 
> Just had another idea. Since we'll end up duplicating these for TX and
> RX (ultimately we'll need RX_BITRATE_40_MHZ/MCS/SGI etc too) we should
> actually do this differently:
> 
>  1) define NL80211_STA_INFO_RATE,
>  2) define NL80211_RATE_INFO_BITRATE/40/MCS/SGI
> 
> and then nest the bitrate information into the STA_INFO_RATE, just like
> station flags are nested etc. That way the RATE_INFO things could also
> be used elsewhere.

So we'll have to add an enum then too to distinguish which rate this is
for.

> >   * Used by the driver to indicate which info in &struct station_info
> >   * it has filled in during get_station() or dump_station().
> > + * Signal strength is only available if driver supports dBm signal
> > + * strength.
> 
> That comment is wrong here since cfg80211 drivers are expected to fill
> this correctly. This comment is about _mac80211_ drivers and thus
> inappropriate in cfg80211.h.

adm8211 is a cfg80211 driver and does not report dBm. So it seems we
currently allow cfg80211 drivers to *not* fill this in properly.
The RTL drivers are some others ones as well as zd1211rw but it seems
we'll be able to correct zd1211rw.

  Luis

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

* Re: RFC Patch v2: Add signal strength to nl80211station info
  2008-12-04 21:12                         ` Luis R. Rodriguez
@ 2008-12-04 21:20                           ` Johannes Berg
  2008-12-05  8:34                             ` Henning Rogge
  0 siblings, 1 reply; 66+ messages in thread
From: Johannes Berg @ 2008-12-04 21:20 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: Henning Rogge, Luis Rodriguez, Henning Rogge, Marcel Holtmann,
	linux-wireless, nbd

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

On Thu, 2008-12-04 at 13:12 -0800, Luis R. Rodriguez wrote:

> > Please remove the RX bitrate for now, the drivers are not currently
> > reporting HT information appropriately.
> 
> It seems that's the case for ath9k, at least Jouni had pointed out to me.

They cannot, we don't even have that in the API.

> > then we also don't need the values for the number of streams since those
> > are perfect multiples (1x, 2x, 3x, 4x for up to 4 streams).
> 
> Well if you have the MCS index and HT mode you get the # of streams. Not
> sure I understood the perfect multiple stuff.

Right, but you don't need to store a bitrate for MCS 0, 8, 16 and 24,
the latter three can just use the first multiplied by 2, 3 and 4
respectively.

> > Just had another idea. Since we'll end up duplicating these for TX and
> > RX (ultimately we'll need RX_BITRATE_40_MHZ/MCS/SGI etc too) we should
> > actually do this differently:
> > 
> >  1) define NL80211_STA_INFO_RATE,
> >  2) define NL80211_RATE_INFO_BITRATE/40/MCS/SGI
> > 
> > and then nest the bitrate information into the STA_INFO_RATE, just like
> > station flags are nested etc. That way the RATE_INFO things could also
> > be used elsewhere.
> 
> So we'll have to add an enum then too to distinguish which rate this is
> for.

No, we know that based on what "container" attribute it's contained in,
in netlink.

> > >   * Used by the driver to indicate which info in &struct station_info
> > >   * it has filled in during get_station() or dump_station().
> > > + * Signal strength is only available if driver supports dBm signal
> > > + * strength.
> > 
> > That comment is wrong here since cfg80211 drivers are expected to fill
> > this correctly. This comment is about _mac80211_ drivers and thus
> > inappropriate in cfg80211.h.
> 
> adm8211 is a cfg80211 driver and does not report dBm. So it seems we
> currently allow cfg80211 drivers to *not* fill this in properly.
> The RTL drivers are some others ones as well as zd1211rw but it seems
> we'll be able to correct zd1211rw.

adm8211 is a mac80211 driver, and mac80211 doesn't fill this information
because of that, I think that's an important distinction. If you feel
this needs to be noted explicitly (it should be obvious since cfg80211
defines it in dBm and the driver cannot give such values) then please
add it to the documentation about the signal HW flags.

johannes

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

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

* Re: RFC Patch v2: Add signal strength to nl80211station info
  2008-12-04 21:20                           ` Johannes Berg
@ 2008-12-05  8:34                             ` Henning Rogge
  2008-12-05  9:45                               ` Johannes Berg
  0 siblings, 1 reply; 66+ messages in thread
From: Henning Rogge @ 2008-12-05  8:34 UTC (permalink / raw)
  To: Johannes Berg
  Cc: Luis R. Rodriguez, Luis Rodriguez, Henning Rogge,
	Marcel Holtmann, linux-wireless, nbd

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

Am Thursday 04 December 2008 22:20:35 schrieb Johannes Berg:
> On Thu, 2008-12-04 at 13:12 -0800, Luis R. Rodriguez wrote:
> > It seems that's the case for ath9k, at least Jouni had pointed out to me.
>
> They cannot, we don't even have that in the API.
Ath9k has it's ***_ratetable which contains a line of data for each 
transmission range. 20/40Mhz and guard interval is already contained in this 
table (encoded in "phy" variable). Just the MCS number is missing.

And I think the intel driver has the necessary data too. If I understand the 
iwl5000 driver, it pushes the rate index (even for 802.11n) through 
ieee80211_rx_status into mac80211.

> > > then we also don't need the values for the number of streams since
> > > those are perfect multiples (1x, 2x, 3x, 4x for up to 4 streams).
> >
> > Well if you have the MCS index and HT mode you get the # of streams. Not
> > sure I understood the perfect multiple stuff.
>
> Right, but you don't need to store a bitrate for MCS 0, 8, 16 and 24,
> the latter three can just use the first multiplied by 2, 3 and 4
> respectively.
When I looked at the table in the wiki I noticed it cannot be created just by 
a little bit arithmetric ? Maybe someone can look at the 802.11 draft if we 
don't need the tables at all but just use a formula ? If yes we could remove 
them from kernelspace and just add a macro for calculating the rate into a 
userspace-accessable header file.

> > > Just had another idea. Since we'll end up duplicating these for TX and
> > > RX (ultimately we'll need RX_BITRATE_40_MHZ/MCS/SGI etc too) we should
> > > actually do this differently:
> > >
> > >  1) define NL80211_STA_INFO_RATE,
> > >  2) define NL80211_RATE_INFO_BITRATE/40/MCS/SGI
> > >
> > > and then nest the bitrate information into the STA_INFO_RATE, just like
> > > station flags are nested etc. That way the RATE_INFO things could also
> > > be used elsewhere.
> >
> > So we'll have to add an enum then too to distinguish which rate this is
> > for.
>
> No, we know that based on what "container" attribute it's contained in,
> in netlink.
So it's possible to define a substructure in the station info in nl80211 ? 
Sounds like a nice way to construct the tx/rx rate.

I will see if I get a "v6" patch ready during the weekend.

Henning

*************************************************
Diplom Informatiker Henning Rogge
Forschungsgesellschaft für
Angewandte Naturwissenschaften e. V. (FGAN) 
Neuenahrer Str. 20, 53343 Wachtberg, Germany
Tel.: 0049 (0)228 9435-961
Fax: 0049 (0)228 9435-685
E-Mail: rogge@fgan.de
Web: www.fgan.de
************************************************
Sitz der Gesellschaft: Bonn
Registergericht: Amtsgericht Bonn VR 2530
Vorstand: Dr. rer. nat. Ralf Dornhaus (Vors.), Prof. Dr. Joachim Ender 
(Stellv.)


[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 197 bytes --]

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

* Re: RFC Patch v2: Add signal strength to nl80211station info
  2008-12-05  8:34                             ` Henning Rogge
@ 2008-12-05  9:45                               ` Johannes Berg
  2008-12-05  9:51                                 ` Henning Rogge
  2008-12-06 14:10                                 ` Henning Rogge
  0 siblings, 2 replies; 66+ messages in thread
From: Johannes Berg @ 2008-12-05  9:45 UTC (permalink / raw)
  To: Henning Rogge
  Cc: Luis R. Rodriguez, Luis Rodriguez, Henning Rogge,
	Marcel Holtmann, linux-wireless, nbd

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

On Fri, 2008-12-05 at 09:34 +0100, Henning Rogge wrote:
> Am Thursday 04 December 2008 22:20:35 schrieb Johannes Berg:
> > On Thu, 2008-12-04 at 13:12 -0800, Luis R. Rodriguez wrote:
> > > It seems that's the case for ath9k, at least Jouni had pointed out to me.
> >
> > They cannot, we don't even have that in the API.
> Ath9k has it's ***_ratetable which contains a line of data for each 
> transmission range. 20/40Mhz and guard interval is already contained in this 
> table (encoded in "phy" variable). Just the MCS number is missing.

Well, yes, but it's not done uniformly across drivers.

> And I think the intel driver has the necessary data too. If I understand the 
> iwl5000 driver, it pushes the rate index (even for 802.11n) through 
> ieee80211_rx_status into mac80211.

Sort of, yes, but again, in a much different way. We really have to
rename struct ieee80211_tx_rate to struct ieee80211_txrx_rate and embed
it into struct ieee80211_rx_status for doing this properly.

> > > > then we also don't need the values for the number of streams since
> > > > those are perfect multiples (1x, 2x, 3x, 4x for up to 4 streams).
> > >
> > > Well if you have the MCS index and HT mode you get the # of streams. Not
> > > sure I understood the perfect multiple stuff.
> >
> > Right, but you don't need to store a bitrate for MCS 0, 8, 16 and 24,
> > the latter three can just use the first multiplied by 2, 3 and 4
> > respectively.
> When I looked at the table in the wiki I noticed it cannot be created just by 
> a little bit arithmetric ? Maybe someone can look at the 802.11 draft if we 
> don't need the tables at all but just use a formula ? If yes we could remove 
> them from kernelspace and just add a macro for calculating the rate into a 
> userspace-accessable header file.

I checked for a bit, but it's not trivial. Cf.
http://www.dsprelated.com/showmessage/92947/1.php

> > > > and then nest the bitrate information into the STA_INFO_RATE, just like
> > > > station flags are nested etc. That way the RATE_INFO things could also
> > > > be used elsewhere.
> > >
> > > So we'll have to add an enum then too to distinguish which rate this is
> > > for.
> >
> > No, we know that based on what "container" attribute it's contained in,
> > in netlink.
> So it's possible to define a substructure in the station info in nl80211 ? 
> Sounds like a nice way to construct the tx/rx rate.

Yes, you do that by nesting. nl80211 already does that for phy info and
many other things, you should be able to figure it out, just look for
nla_nest_start/nla_nest_end.

> I will see if I get a "v6" patch ready during the weekend.

Thanks!

johannes

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

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

* Re: RFC Patch v2: Add signal strength to nl80211station info
  2008-12-05  9:45                               ` Johannes Berg
@ 2008-12-05  9:51                                 ` Henning Rogge
  2008-12-05  9:54                                   ` Johannes Berg
  2008-12-06 14:10                                 ` Henning Rogge
  1 sibling, 1 reply; 66+ messages in thread
From: Henning Rogge @ 2008-12-05  9:51 UTC (permalink / raw)
  To: Johannes Berg
  Cc: Luis R. Rodriguez, Luis Rodriguez, Henning Rogge,
	Marcel Holtmann, linux-wireless, nbd

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

Am Friday 05 December 2008 10:45:10 schrieb Johannes Berg:
> > Ath9k has it's ***_ratetable which contains a line of data for each
> > transmission range. 20/40Mhz and guard interval is already contained in
> > this table (encoded in "phy" variable). Just the MCS number is missing.
>
> Well, yes, but it's not done uniformly across drivers.
>
> > And I think the intel driver has the necessary data too. If I understand
> > the iwl5000 driver, it pushes the rate index (even for 802.11n) through
> > ieee80211_rx_status into mac80211.
>
> Sort of, yes, but again, in a much different way. We really have to
> rename struct ieee80211_tx_rate to struct ieee80211_txrx_rate and embed
> it into struct ieee80211_rx_status for doing this properly.
How many 802.11n capable drivers exist in mac80211 at the moment ?

Henning

*************************************************
Diplom Informatiker Henning Rogge
Forschungsgesellschaft für
Angewandte Naturwissenschaften e. V. (FGAN) 
Neuenahrer Str. 20, 53343 Wachtberg, Germany
Tel.: 0049 (0)228 9435-961
Fax: 0049 (0)228 9435-685
E-Mail: rogge@fgan.de
Web: www.fgan.de
************************************************
Sitz der Gesellschaft: Bonn
Registergericht: Amtsgericht Bonn VR 2530
Vorstand: Dr. rer. nat. Ralf Dornhaus (Vors.), Prof. Dr. Joachim Ender 
(Stellv.)


[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 197 bytes --]

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

* Re: RFC Patch v2: Add signal strength to nl80211station info
  2008-12-05  9:51                                 ` Henning Rogge
@ 2008-12-05  9:54                                   ` Johannes Berg
  2008-12-05 23:26                                     ` Henning Rogge
  0 siblings, 1 reply; 66+ messages in thread
From: Johannes Berg @ 2008-12-05  9:54 UTC (permalink / raw)
  To: Henning Rogge
  Cc: Luis R. Rodriguez, Henning Rogge, Marcel Holtmann, linux-wireless, nbd

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

On Fri, 2008-12-05 at 10:51 +0100, Henning Rogge wrote:
> Am Friday 05 December 2008 10:45:10 schrieb Johannes Berg:
> > > Ath9k has it's ***_ratetable which contains a line of data for each
> > > transmission range. 20/40Mhz and guard interval is already contained in
> > > this table (encoded in "phy" variable). Just the MCS number is missing.
> >
> > Well, yes, but it's not done uniformly across drivers.
> >
> > > And I think the intel driver has the necessary data too. If I understand
> > > the iwl5000 driver, it pushes the rate index (even for 802.11n) through
> > > ieee80211_rx_status into mac80211.
> >
> > Sort of, yes, but again, in a much different way. We really have to
> > rename struct ieee80211_tx_rate to struct ieee80211_txrx_rate and embed
> > it into struct ieee80211_rx_status for doing this properly.

> How many 802.11n capable drivers exist in mac80211 at the moment ?

Only those two, really, but more are in development, for example ar9170
and rt2800.

johannes

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

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

* Re: RFC Patch v2: Add signal strength to nl80211station info
  2008-12-05  9:54                                   ` Johannes Berg
@ 2008-12-05 23:26                                     ` Henning Rogge
  2008-12-06  9:15                                       ` Johannes Berg
  0 siblings, 1 reply; 66+ messages in thread
From: Henning Rogge @ 2008-12-05 23:26 UTC (permalink / raw)
  To: linux-wireless

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

I just did a few calculations about the tx/rx rates in 802.11n and I think I 
can replace all of them with simple integer arithmetics. Only the 20Mhz rates 
with short guard interval are a little bit off (I think I miss two of them by 
0.1 MBit/s and one of them by 0.2 MBit/s)...

do you think that's accurate enough ?

Henning

[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 197 bytes --]

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

* Re: RFC Patch v2: Add signal strength to nl80211station info
  2008-12-05 23:26                                     ` Henning Rogge
@ 2008-12-06  9:15                                       ` Johannes Berg
  2008-12-06 11:12                                         ` Henning Rogge
  0 siblings, 1 reply; 66+ messages in thread
From: Johannes Berg @ 2008-12-06  9:15 UTC (permalink / raw)
  To: Henning Rogge; +Cc: linux-wireless

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

On Sat, 2008-12-06 at 00:26 +0100, Henning Rogge wrote:
> I just did a few calculations about the tx/rx rates in 802.11n and I think I 
> can replace all of them with simple integer arithmetics. Only the 20Mhz rates 
> with short guard interval are a little bit off (I think I miss two of them by 
> 0.1 MBit/s and one of them by 0.2 MBit/s)...
> 
> do you think that's accurate enough ?

Yes, well, depending on which values you used you might have run into
the fact that the values from the tables were already rounded.

johannes

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

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

* Re: RFC Patch v2: Add signal strength to nl80211station info
  2008-12-06  9:15                                       ` Johannes Berg
@ 2008-12-06 11:12                                         ` Henning Rogge
  0 siblings, 0 replies; 66+ messages in thread
From: Henning Rogge @ 2008-12-06 11:12 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linux-wireless

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

On Saturday 06 December 2008 10:15:20 Johannes Berg wrote:
> Yes, well, depending on which values you used you might have run into
> the fact that the values from the tables were already rounded.
Both  errors happen for 20 Mhz channels... one of them is definitely a typo in 
the wiki.

I get 144.4 MBit/s (wiki says 144.0) for MCS 15 (long GI)
and 115.6 MBit/s (wiki says 173.3, which is a typo !) for MCS 27(short GI).

in pseudocode:
-----------------

int modulation = mcs & 7;
int streams = mcs / 8;

int bitrate = (flags & 40MHZ) ? 13500000 : 6500000;

if (modulation < 4)
    bitrate *= (modulation + 1);
else if (modulation == 4)
    bitrate *= (modulation + 2);
else
    bitrate *= (modulation + 3);

bitrate *= streams;

if (flags & SHORT_GI)
    bitrate = (bitrate * 10) / 9;

return (bitrate + 50000) / 100000; // do NOT just round down

Henning


[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 197 bytes --]

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

* Re: RFC Patch v2: Add signal strength to nl80211station info
  2008-12-05  9:45                               ` Johannes Berg
  2008-12-05  9:51                                 ` Henning Rogge
@ 2008-12-06 14:10                                 ` Henning Rogge
  2008-12-06 14:43                                   ` Henning Rogge
  2008-12-06 14:51                                   ` Johannes Berg
  1 sibling, 2 replies; 66+ messages in thread
From: Henning Rogge @ 2008-12-06 14:10 UTC (permalink / raw)
  To: Johannes Berg
  Cc: Henning Rogge, Luis R. Rodriguez, Luis Rodriguez,
	Marcel Holtmann, linux-wireless, nbd


[-- Attachment #1.1: Type: text/plain, Size: 1272 bytes --]

Okay, here is v6 of my patch... feel free to rip it apart. ;)

Changes since v1:
- removed noise and quality from station info in NL80211
- added bandwith to station info in NL80211
- changed name of patch file to nl80211ext_v2.patch
 
Changes since v2:
- added kernel comment lines for new fields/enums
- changed name of "bandwith" field to tx_bitrate

Changes since v3:
- added rx_bitrate to station info and sta_info
- remember bitrate of last received unicast packet to this station
- decode 802.11n MCS index for nl80211
  (maybe this should be ported to WEXT too ?)

Changes since v4:
- added tx_bitrate_flags adn tx_bitrate_mcs field to station info
- added flags for 40Mhz and small guard interval to NL80211 station info
- added mcs field to NL80211 station info

Changes since v5:
- remove rx_bitrate from patch until we get a sane way to learn the details of 
received 802.11n packages
-replace 802.11n bitrate arrays with calculation based on basic rates
- pushed txrate nl80211 stationinfo into nested attribute
- created station_info_rate_flags enum to save bitrate flags in station_info
- cleanup of kerneldoc

TODO:
- push magic numbers of sta_get_80211n_bitrate (65/135) into constants
- coding style cleanup

Henning


[-- Attachment #1.2: nl80211ext_v6.patch --]
[-- Type: text/x-patch, Size: 8777 bytes --]

diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index 04d4516..e14caa9 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -425,6 +425,30 @@ enum nl80211_sta_flags {
 };
 
 /**
+ * enum nl80211_sta_info_rate - station information about bitrate
+ *
+ * These attribute types are used with %NL80211_STA_INFO_TXRATE
+ * when getting information about the bitrate of a station.
+ *
+ * @__NL80211_STA_INFO_RATE_INVALID: attribute number 0 is reserved
+ * @NL80211_STA_INFO_RATE_TOTAL: total bitrate (u16, 100kbit/s)
+ * @NL80211_STA_INFO_RATE_MCS: mcs index for 802.11n (u8)
+ * @NL80211_STA_INFO_RATE_40_MHZ_WIDTH: 40 Mhz dualchannel bitrate
+ * @NL80211_STA_INFO_RATE_SHORT_GI: 400ns guard interval
+ */
+enum nl80211_sta_info_rate {
+	__NL80211_STA_INFO_RATE_INVALID,
+	NL80211_STA_INFO_RATE_TOTAL,
+	NL80211_STA_INFO_RATE_MCS,
+	NL80211_STA_INFO_RATE_40_MHZ_WIDTH,
+	NL80211_STA_INFO_RATE_SHORT_GI,
+
+	/* keep last */
+	__NL80211_STA_INFO_RATE_AFTER_LAST,
+	NL80211_STA_INFO_RATE_MAX = __NL80211_STA_INFO_RATE_AFTER_LAST - 1
+};
+
+/**
  * enum nl80211_sta_info - station information
  *
  * These attribute types are used with %NL80211_ATTR_STA_INFO
@@ -436,6 +460,9 @@ enum nl80211_sta_flags {
  * @NL80211_STA_INFO_TX_BYTES: total transmitted bytes (u32, to this station)
  * @__NL80211_STA_INFO_AFTER_LAST: internal
  * @NL80211_STA_INFO_MAX: highest possible station info attribute
+ * @NL80211_STA_INFO_SIGNAL: signal strength of last received package (u8, dBm)
+ * @NL80211_STA_INFO_TX_BITRATE: current unicast tx rate, nested attribute
+ *  containing info as possible, see &enum nl80211_sta_info_txrate.
  */
 enum nl80211_sta_info {
 	__NL80211_STA_INFO_INVALID,
@@ -445,6 +472,8 @@ enum nl80211_sta_info {
 	NL80211_STA_INFO_LLID,
 	NL80211_STA_INFO_PLID,
 	NL80211_STA_INFO_PLINK_STATE,
+	NL80211_STA_INFO_SIGNAL,
+	NL80211_STA_INFO_TX_BITRATE,
 
 	/* keep last */
 	__NL80211_STA_INFO_AFTER_LAST,
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index a0c0bf1..9ebcb11 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -169,6 +169,10 @@ struct station_parameters {
  * @STATION_INFO_LLID: @llid filled
  * @STATION_INFO_PLID: @plid filled
  * @STATION_INFO_PLINK_STATE: @plink_state filled
+ * @STATION_INFO_SIGNAL: @signal filled
+ * @STATION_INFO_RX_BITRATE: @rx_bitrate filled
+ * @STATION_INFO_TX_BITRATE: @tx_bitrate fields are filled
+ *  (tx_bitrate, tx_bitrate_flags and tx_bitrate_mcs)
  */
 enum station_info_flags {
 	STATION_INFO_INACTIVE_TIME	= 1<<0,
@@ -177,6 +181,25 @@ enum station_info_flags {
 	STATION_INFO_LLID		= 1<<3,
 	STATION_INFO_PLID		= 1<<4,
 	STATION_INFO_PLINK_STATE	= 1<<5,
+	STATION_INFO_SIGNAL		= 1<<6,
+	STATION_INFO_RX_BITRATE		= 1<<7,
+	STATION_INFO_TX_BITRATE		= 1<<8,
+};
+
+/**
+ * enum station_info_rate_flags - station transmission rate flags
+ *
+ * Used by the driver to indicate the specific rate transmission
+ * type for 802.11n transmissions.
+ *
+ * @STATION_INFO_BITRATE_MCS: @tx_bitrate_mcs filled
+ * @STATION_INFO_BITRATE_40_MHZ_WIDTH: 40 Mhz width transmission
+ * @STATION_INFO_BITRATE_SHORT_GI: 400ns guard interval
+ */
+enum station_info_rate_flags {
+	STATION_INFO_BITRATE_MCS		= 1<<0,
+	STATION_INFO_BITRATE_40_MHZ_WIDTH	= 1<<1,
+	STATION_INFO_BITRATE_SHORT_GI		= 1<<2,
 };
 
 /**
@@ -191,6 +214,11 @@ enum station_info_flags {
  * @llid: mesh local link id
  * @plid: mesh peer link id
  * @plink_state: mesh peer link state
+ * @signal: signal strength of last received package in dBm
+ * @txrate_total: current unicast bitrate to this station in 100 kbit/sec
+ * @txrate_flags: bitflag of flags from &enum station_info_bitrate_flags
+ * @txrate_mcs: MCS index of a 802.11n transmission, see
+ *  &enum station_info_bitrate_flags
  */
 struct station_info {
 	u32 filled;
@@ -200,6 +228,10 @@ struct station_info {
 	u16 llid;
 	u16 plid;
 	u8 plink_state;
+	u8 signal;
+	u16 txrate_total;
+	u8 txrate_flags;
+	u8 txrate_mcs;
 };
 
 /**
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 7a7a6c1..3567cd9 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -304,18 +304,65 @@ static int ieee80211_config_default_key(struct wiphy *wiphy,
 	return 0;
 }
 
+static u16 sta_get_80211n_bitrate(struct ieee80211_tx_rate *rate)
+{
+	int modulation = rate->idx & 7;
+	int streams = rate->idx >> 3;
+
+	int bitrate = (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) ? 13500000 : 6500000;
+
+	if (modulation < 4)
+		bitrate *= (modulation + 1);
+	else if (modulation == 4)
+		bitrate *= (modulation + 2);
+	else
+		bitrate *= (modulation + 3);
+
+	bitrate *= streams;
+
+	if (rate->flags & IEEE80211_TX_RC_SHORT_GI)
+		bitrate = (bitrate * 10) / 9;
+
+	return (bitrate + 50000) / 100000; // do NOT just round down
+}
+
 static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
 {
 	struct ieee80211_sub_if_data *sdata = sta->sdata;
 
 	sinfo->filled = STATION_INFO_INACTIVE_TIME |
 			STATION_INFO_RX_BYTES |
-			STATION_INFO_TX_BYTES;
+			STATION_INFO_TX_BYTES |
+			STATION_INFO_RX_BITRATE |
+			STATION_INFO_TX_BITRATE;
 
 	sinfo->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx);
 	sinfo->rx_bytes = sta->rx_bytes;
 	sinfo->tx_bytes = sta->tx_bytes;
 
+	if (sta->local->hw.flags & IEEE80211_HW_SIGNAL_DBM) {
+		sinfo->filled |= STATION_INFO_SIGNAL;
+		sinfo->signal = sta->last_signal;
+	}
+
+	sinfo->txrate_flags = 0;
+	if (sta->last_tx_rate.flags & IEEE80211_TX_RC_MCS)
+		sinfo->txrate_flags |= STATION_INFO_BITRATE_MCS;
+	if (sta->last_tx_rate.flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
+		sinfo->txrate_flags |= STATION_INFO_BITRATE_40_MHZ_WIDTH;
+	if (sta->last_tx_rate.flags & IEEE80211_TX_RC_SHORT_GI)
+		sinfo->txrate_flags |= STATION_INFO_BITRATE_SHORT_GI;
+
+	if (!(sta->last_tx_rate.flags & IEEE80211_TX_RC_MCS)) {
+		struct ieee80211_supported_band *sband;
+		sband = sta->local->hw.wiphy->bands[sta->local->hw.conf.channel->band];
+		sinfo->txrate_total = sband->bitrates[sta->last_tx_rate.idx].bitrate;
+	}
+	else {
+		sinfo->txrate_total = sta_get_80211n_bitrate(&sta->last_tx_rate);
+		sinfo->txrate_mcs = sta->last_tx_rate.idx;
+	}
+
 	if (ieee80211_vif_is_mesh(&sdata->vif)) {
 #ifdef CONFIG_MAC80211_MESH
 		sinfo->filled |= STATION_INFO_LLID |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 59f356a..84922b0 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -727,8 +727,9 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
 	if (rx->sdata->vif.type == NL80211_IFTYPE_ADHOC) {
 		u8 *bssid = ieee80211_get_bssid(hdr, rx->skb->len,
 						NL80211_IFTYPE_ADHOC);
-		if (compare_ether_addr(bssid, rx->sdata->u.sta.bssid) == 0)
+		if (compare_ether_addr(bssid, rx->sdata->u.sta.bssid) == 0) {
 			sta->last_rx = jiffies;
+		}
 	} else
 	if (!is_multicast_ether_addr(hdr->addr1) ||
 	    rx->sdata->vif.type == NL80211_IFTYPE_STATION) {
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 9caee60..197dc4d 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -16,6 +16,7 @@
 #include <linux/netlink.h>
 #include <net/genetlink.h>
 #include <net/cfg80211.h>
+#include <net/mac80211.h>
 #include "core.h"
 #include "nl80211.h"
 #include "reg.h"
@@ -1084,7 +1085,7 @@ static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
 				u8 *mac_addr, struct station_info *sinfo)
 {
 	void *hdr;
-	struct nlattr *sinfoattr;
+	struct nlattr *sinfoattr, *txrate;
 
 	hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_STATION);
 	if (!hdr)
@@ -1114,7 +1115,27 @@ static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
 	if (sinfo->filled & STATION_INFO_PLINK_STATE)
 		NLA_PUT_U8(msg, NL80211_STA_INFO_PLINK_STATE,
 			    sinfo->plink_state);
+	if (sinfo->filled & STATION_INFO_SIGNAL)
+		NLA_PUT_U8(msg, NL80211_STA_INFO_SIGNAL,
+			   sinfo->signal);
+	if (sinfo->filled & STATION_INFO_TX_BITRATE) {
+		txrate = nla_nest_start(msg, NL80211_STA_INFO_TX_BITRATE);
+		if (!txrate)
+			goto nla_put_failure;
+
+		NLA_PUT_U16(msg, NL80211_STA_INFO_RATE_TOTAL,
+			    sinfo->txrate_total);
 
+		if (sinfo->txrate_flags & STATION_INFO_BITRATE_MCS)
+			NLA_PUT_U16(msg, NL80211_STA_INFO_RATE_MCS,
+				    sinfo->txrate_mcs);
+		if (sinfo->txrate_flags & STATION_INFO_BITRATE_40_MHZ_WIDTH)
+			NLA_PUT_FLAG(msg, NL80211_STA_INFO_RATE_40_MHZ_WIDTH);
+		if (sinfo->txrate_flags & STATION_INFO_BITRATE_SHORT_GI)
+			NLA_PUT_FLAG(msg, NL80211_STA_INFO_RATE_SHORT_GI);
+
+		nla_nest_end(msg, txrate);
+	}
 	nla_nest_end(msg, sinfoattr);
 
 	return genlmsg_end(msg, hdr);

[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 197 bytes --]

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

* Re: RFC Patch v2: Add signal strength to nl80211station info
  2008-12-06 14:10                                 ` Henning Rogge
@ 2008-12-06 14:43                                   ` Henning Rogge
  2008-12-06 14:51                                   ` Johannes Berg
  1 sibling, 0 replies; 66+ messages in thread
From: Henning Rogge @ 2008-12-06 14:43 UTC (permalink / raw)
  To: Johannes Berg
  Cc: Henning Rogge, Luis R. Rodriguez, Luis Rodriguez,
	Marcel Holtmann, linux-wireless, nbd


[-- Attachment #1.1: Type: text/plain, Size: 10132 bytes --]

Okay, here is v6 of my patch... feel free to rip it apart. ;)
(forgot to put the patch inline too... sorry)

Changes since v1:
- removed noise and quality from station info in NL80211
- added bandwith to station info in NL80211
- changed name of patch file to nl80211ext_v2.patch
  
Changes since v2:
- added kernel comment lines for new fields/enums
- changed name of "bandwith" field to tx_bitrate

Changes since v3:
- added rx_bitrate to station info and sta_info
- remember bitrate of last received unicast packet to this station
- decode 802.11n MCS index for nl80211
  (maybe this should be ported to WEXT too ?)

Changes since v4:
- added tx_bitrate_flags adn tx_bitrate_mcs field to station info
- added flags for 40Mhz and small guard interval to NL80211 station info
- added mcs field to NL80211 station info

Changes since v5:
- remove rx_bitrate from patch until we get a sane way to learn the details of 
received 802.11n packages
-replace 802.11n bitrate arrays with calculation based on basic rates
- pushed txrate nl80211 stationinfo into nested attribute
- created station_info_rate_flags enum to save bitrate flags in
station_info - cleanup of kerneldoc

TODO:
- push magic numbers of sta_get_80211n_bitrate (65/135) into constants
- coding style cleanup

Henning
-----------------------
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index 04d4516..e14caa9 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -425,6 +425,30 @@ enum nl80211_sta_flags {
 };
 
 /**
+ * enum nl80211_sta_info_rate - station information about bitrate
+ *
+ * These attribute types are used with %NL80211_STA_INFO_TXRATE
+ * when getting information about the bitrate of a station.
+ *
+ * @__NL80211_STA_INFO_RATE_INVALID: attribute number 0 is reserved
+ * @NL80211_STA_INFO_RATE_TOTAL: total bitrate (u16, 100kbit/s)
+ * @NL80211_STA_INFO_RATE_MCS: mcs index for 802.11n (u8)
+ * @NL80211_STA_INFO_RATE_40_MHZ_WIDTH: 40 Mhz dualchannel bitrate
+ * @NL80211_STA_INFO_RATE_SHORT_GI: 400ns guard interval
+ */
+enum nl80211_sta_info_rate {
+	__NL80211_STA_INFO_RATE_INVALID,
+	NL80211_STA_INFO_RATE_TOTAL,
+	NL80211_STA_INFO_RATE_MCS,
+	NL80211_STA_INFO_RATE_40_MHZ_WIDTH,
+	NL80211_STA_INFO_RATE_SHORT_GI,
+
+	/* keep last */
+	__NL80211_STA_INFO_RATE_AFTER_LAST,
+	NL80211_STA_INFO_RATE_MAX = __NL80211_STA_INFO_RATE_AFTER_LAST - 1
+};
+
+/**
  * enum nl80211_sta_info - station information
  *
  * These attribute types are used with %NL80211_ATTR_STA_INFO
@@ -436,6 +460,9 @@ enum nl80211_sta_flags {
  * @NL80211_STA_INFO_TX_BYTES: total transmitted bytes (u32, to this station)
  * @__NL80211_STA_INFO_AFTER_LAST: internal
  * @NL80211_STA_INFO_MAX: highest possible station info attribute
+ * @NL80211_STA_INFO_SIGNAL: signal strength of last received package (u8, 
dBm)
+ * @NL80211_STA_INFO_TX_BITRATE: current unicast tx rate, nested attribute
+ *  containing info as possible, see &enum nl80211_sta_info_txrate.
  */
 enum nl80211_sta_info {
 	__NL80211_STA_INFO_INVALID,
@@ -445,6 +472,8 @@ enum nl80211_sta_info {
 	NL80211_STA_INFO_LLID,
 	NL80211_STA_INFO_PLID,
 	NL80211_STA_INFO_PLINK_STATE,
+	NL80211_STA_INFO_SIGNAL,
+	NL80211_STA_INFO_TX_BITRATE,
 
 	/* keep last */
 	__NL80211_STA_INFO_AFTER_LAST,
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index a0c0bf1..9ebcb11 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -169,6 +169,10 @@ struct station_parameters {
  * @STATION_INFO_LLID: @llid filled
  * @STATION_INFO_PLID: @plid filled
  * @STATION_INFO_PLINK_STATE: @plink_state filled
+ * @STATION_INFO_SIGNAL: @signal filled
+ * @STATION_INFO_RX_BITRATE: @rx_bitrate filled
+ * @STATION_INFO_TX_BITRATE: @tx_bitrate fields are filled
+ *  (tx_bitrate, tx_bitrate_flags and tx_bitrate_mcs)
  */
 enum station_info_flags {
 	STATION_INFO_INACTIVE_TIME	= 1<<0,
@@ -177,6 +181,25 @@ enum station_info_flags {
 	STATION_INFO_LLID		= 1<<3,
 	STATION_INFO_PLID		= 1<<4,
 	STATION_INFO_PLINK_STATE	= 1<<5,
+	STATION_INFO_SIGNAL		= 1<<6,
+	STATION_INFO_RX_BITRATE		= 1<<7,
+	STATION_INFO_TX_BITRATE		= 1<<8,
+};
+
+/**
+ * enum station_info_rate_flags - station transmission rate flags
+ *
+ * Used by the driver to indicate the specific rate transmission
+ * type for 802.11n transmissions.
+ *
+ * @STATION_INFO_BITRATE_MCS: @tx_bitrate_mcs filled
+ * @STATION_INFO_BITRATE_40_MHZ_WIDTH: 40 Mhz width transmission
+ * @STATION_INFO_BITRATE_SHORT_GI: 400ns guard interval
+ */
+enum station_info_rate_flags {
+	STATION_INFO_BITRATE_MCS		= 1<<0,
+	STATION_INFO_BITRATE_40_MHZ_WIDTH	= 1<<1,
+	STATION_INFO_BITRATE_SHORT_GI		= 1<<2,
 };
 
 /**
@@ -191,6 +214,11 @@ enum station_info_flags {
  * @llid: mesh local link id
  * @plid: mesh peer link id
  * @plink_state: mesh peer link state
+ * @signal: signal strength of last received package in dBm
+ * @txrate_total: current unicast bitrate to this station in 100 kbit/sec
+ * @txrate_flags: bitflag of flags from &enum station_info_bitrate_flags
+ * @txrate_mcs: MCS index of a 802.11n transmission, see
+ *  &enum station_info_bitrate_flags
  */
 struct station_info {
 	u32 filled;
@@ -200,6 +228,10 @@ struct station_info {
 	u16 llid;
 	u16 plid;
 	u8 plink_state;
+	u8 signal;
+	u16 txrate_total;
+	u8 txrate_flags;
+	u8 txrate_mcs;
 };
 
 /**
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 7a7a6c1..3567cd9 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -304,18 +304,65 @@ static int ieee80211_config_default_key(struct wiphy 
*wiphy,
 	return 0;
 }
 
+static u16 sta_get_80211n_bitrate(struct ieee80211_tx_rate *rate)
+{
+	int modulation = rate->idx & 7;
+	int streams = rate->idx >> 3;
+
+	int bitrate = (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) ? 13500000 : 
6500000;
+
+	if (modulation < 4)
+		bitrate *= (modulation + 1);
+	else if (modulation == 4)
+		bitrate *= (modulation + 2);
+	else
+		bitrate *= (modulation + 3);
+
+	bitrate *= streams;
+
+	if (rate->flags & IEEE80211_TX_RC_SHORT_GI)
+		bitrate = (bitrate * 10) / 9;
+
+	return (bitrate + 50000) / 100000; // do NOT just round down
+}
+
 static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
 {
 	struct ieee80211_sub_if_data *sdata = sta->sdata;
 
 	sinfo->filled = STATION_INFO_INACTIVE_TIME |
 			STATION_INFO_RX_BYTES |
-			STATION_INFO_TX_BYTES;
+			STATION_INFO_TX_BYTES |
+			STATION_INFO_RX_BITRATE |
+			STATION_INFO_TX_BITRATE;
 
 	sinfo->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx);
 	sinfo->rx_bytes = sta->rx_bytes;
 	sinfo->tx_bytes = sta->tx_bytes;
 
+	if (sta->local->hw.flags & IEEE80211_HW_SIGNAL_DBM) {
+		sinfo->filled |= STATION_INFO_SIGNAL;
+		sinfo->signal = sta->last_signal;
+	}
+
+	sinfo->txrate_flags = 0;
+	if (sta->last_tx_rate.flags & IEEE80211_TX_RC_MCS)
+		sinfo->txrate_flags |= STATION_INFO_BITRATE_MCS;
+	if (sta->last_tx_rate.flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
+		sinfo->txrate_flags |= STATION_INFO_BITRATE_40_MHZ_WIDTH;
+	if (sta->last_tx_rate.flags & IEEE80211_TX_RC_SHORT_GI)
+		sinfo->txrate_flags |= STATION_INFO_BITRATE_SHORT_GI;
+
+	if (!(sta->last_tx_rate.flags & IEEE80211_TX_RC_MCS)) {
+		struct ieee80211_supported_band *sband;
+		sband = sta->local->hw.wiphy->bands[sta->local->hw.conf.channel->band];
+		sinfo->txrate_total = sband->bitrates[sta->last_tx_rate.idx].bitrate;
+	}
+	else {
+		sinfo->txrate_total = sta_get_80211n_bitrate(&sta->last_tx_rate);
+		sinfo->txrate_mcs = sta->last_tx_rate.idx;
+	}
+
 	if (ieee80211_vif_is_mesh(&sdata->vif)) {
 #ifdef CONFIG_MAC80211_MESH
 		sinfo->filled |= STATION_INFO_LLID |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 59f356a..84922b0 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -727,8 +727,9 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
 	if (rx->sdata->vif.type == NL80211_IFTYPE_ADHOC) {
 		u8 *bssid = ieee80211_get_bssid(hdr, rx->skb->len,
 						NL80211_IFTYPE_ADHOC);
-		if (compare_ether_addr(bssid, rx->sdata->u.sta.bssid) == 0)
+		if (compare_ether_addr(bssid, rx->sdata->u.sta.bssid) == 0) {
 			sta->last_rx = jiffies;
+		}
 	} else
 	if (!is_multicast_ether_addr(hdr->addr1) ||
 	    rx->sdata->vif.type == NL80211_IFTYPE_STATION) {
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 9caee60..197dc4d 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -16,6 +16,7 @@
 #include <linux/netlink.h>
 #include <net/genetlink.h>
 #include <net/cfg80211.h>
+#include <net/mac80211.h>
 #include "core.h"
 #include "nl80211.h"
 #include "reg.h"
@@ -1084,7 +1085,7 @@ static int nl80211_send_station(struct sk_buff *msg, u32 
pid, u32 seq,
 				u8 *mac_addr, struct station_info *sinfo)
 {
 	void *hdr;
-	struct nlattr *sinfoattr;
+	struct nlattr *sinfoattr, *txrate;
 
 	hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_STATION);
 	if (!hdr)
@@ -1114,7 +1115,27 @@ static int nl80211_send_station(struct sk_buff *msg, 
u32 pid, u32 seq,
 	if (sinfo->filled & STATION_INFO_PLINK_STATE)
 		NLA_PUT_U8(msg, NL80211_STA_INFO_PLINK_STATE,
 			    sinfo->plink_state);
+	if (sinfo->filled & STATION_INFO_SIGNAL)
+		NLA_PUT_U8(msg, NL80211_STA_INFO_SIGNAL,
+			   sinfo->signal);
+	if (sinfo->filled & STATION_INFO_TX_BITRATE) {
+		txrate = nla_nest_start(msg, NL80211_STA_INFO_TX_BITRATE);
+		if (!txrate)
+			goto nla_put_failure;
+
+		NLA_PUT_U16(msg, NL80211_STA_INFO_RATE_TOTAL,
+			    sinfo->txrate_total);
 
+		if (sinfo->txrate_flags & STATION_INFO_BITRATE_MCS)
+			NLA_PUT_U16(msg, NL80211_STA_INFO_RATE_MCS,
+				    sinfo->txrate_mcs);
+		if (sinfo->txrate_flags & STATION_INFO_BITRATE_40_MHZ_WIDTH)
+			NLA_PUT_FLAG(msg, NL80211_STA_INFO_RATE_40_MHZ_WIDTH);
+		if (sinfo->txrate_flags & STATION_INFO_BITRATE_SHORT_GI)
+			NLA_PUT_FLAG(msg, NL80211_STA_INFO_RATE_SHORT_GI);
+
+		nla_nest_end(msg, txrate);
+	}
 	nla_nest_end(msg, sinfoattr);
 
 	return genlmsg_end(msg, hdr);


[-- Attachment #1.2: nl80211ext_v6.patch --]
[-- Type: text/x-patch, Size: 8777 bytes --]

diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index 04d4516..e14caa9 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -425,6 +425,30 @@ enum nl80211_sta_flags {
 };
 
 /**
+ * enum nl80211_sta_info_rate - station information about bitrate
+ *
+ * These attribute types are used with %NL80211_STA_INFO_TXRATE
+ * when getting information about the bitrate of a station.
+ *
+ * @__NL80211_STA_INFO_RATE_INVALID: attribute number 0 is reserved
+ * @NL80211_STA_INFO_RATE_TOTAL: total bitrate (u16, 100kbit/s)
+ * @NL80211_STA_INFO_RATE_MCS: mcs index for 802.11n (u8)
+ * @NL80211_STA_INFO_RATE_40_MHZ_WIDTH: 40 Mhz dualchannel bitrate
+ * @NL80211_STA_INFO_RATE_SHORT_GI: 400ns guard interval
+ */
+enum nl80211_sta_info_rate {
+	__NL80211_STA_INFO_RATE_INVALID,
+	NL80211_STA_INFO_RATE_TOTAL,
+	NL80211_STA_INFO_RATE_MCS,
+	NL80211_STA_INFO_RATE_40_MHZ_WIDTH,
+	NL80211_STA_INFO_RATE_SHORT_GI,
+
+	/* keep last */
+	__NL80211_STA_INFO_RATE_AFTER_LAST,
+	NL80211_STA_INFO_RATE_MAX = __NL80211_STA_INFO_RATE_AFTER_LAST - 1
+};
+
+/**
  * enum nl80211_sta_info - station information
  *
  * These attribute types are used with %NL80211_ATTR_STA_INFO
@@ -436,6 +460,9 @@ enum nl80211_sta_flags {
  * @NL80211_STA_INFO_TX_BYTES: total transmitted bytes (u32, to this station)
  * @__NL80211_STA_INFO_AFTER_LAST: internal
  * @NL80211_STA_INFO_MAX: highest possible station info attribute
+ * @NL80211_STA_INFO_SIGNAL: signal strength of last received package (u8, dBm)
+ * @NL80211_STA_INFO_TX_BITRATE: current unicast tx rate, nested attribute
+ *  containing info as possible, see &enum nl80211_sta_info_txrate.
  */
 enum nl80211_sta_info {
 	__NL80211_STA_INFO_INVALID,
@@ -445,6 +472,8 @@ enum nl80211_sta_info {
 	NL80211_STA_INFO_LLID,
 	NL80211_STA_INFO_PLID,
 	NL80211_STA_INFO_PLINK_STATE,
+	NL80211_STA_INFO_SIGNAL,
+	NL80211_STA_INFO_TX_BITRATE,
 
 	/* keep last */
 	__NL80211_STA_INFO_AFTER_LAST,
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index a0c0bf1..9ebcb11 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -169,6 +169,10 @@ struct station_parameters {
  * @STATION_INFO_LLID: @llid filled
  * @STATION_INFO_PLID: @plid filled
  * @STATION_INFO_PLINK_STATE: @plink_state filled
+ * @STATION_INFO_SIGNAL: @signal filled
+ * @STATION_INFO_RX_BITRATE: @rx_bitrate filled
+ * @STATION_INFO_TX_BITRATE: @tx_bitrate fields are filled
+ *  (tx_bitrate, tx_bitrate_flags and tx_bitrate_mcs)
  */
 enum station_info_flags {
 	STATION_INFO_INACTIVE_TIME	= 1<<0,
@@ -177,6 +181,25 @@ enum station_info_flags {
 	STATION_INFO_LLID		= 1<<3,
 	STATION_INFO_PLID		= 1<<4,
 	STATION_INFO_PLINK_STATE	= 1<<5,
+	STATION_INFO_SIGNAL		= 1<<6,
+	STATION_INFO_RX_BITRATE		= 1<<7,
+	STATION_INFO_TX_BITRATE		= 1<<8,
+};
+
+/**
+ * enum station_info_rate_flags - station transmission rate flags
+ *
+ * Used by the driver to indicate the specific rate transmission
+ * type for 802.11n transmissions.
+ *
+ * @STATION_INFO_BITRATE_MCS: @tx_bitrate_mcs filled
+ * @STATION_INFO_BITRATE_40_MHZ_WIDTH: 40 Mhz width transmission
+ * @STATION_INFO_BITRATE_SHORT_GI: 400ns guard interval
+ */
+enum station_info_rate_flags {
+	STATION_INFO_BITRATE_MCS		= 1<<0,
+	STATION_INFO_BITRATE_40_MHZ_WIDTH	= 1<<1,
+	STATION_INFO_BITRATE_SHORT_GI		= 1<<2,
 };
 
 /**
@@ -191,6 +214,11 @@ enum station_info_flags {
  * @llid: mesh local link id
  * @plid: mesh peer link id
  * @plink_state: mesh peer link state
+ * @signal: signal strength of last received package in dBm
+ * @txrate_total: current unicast bitrate to this station in 100 kbit/sec
+ * @txrate_flags: bitflag of flags from &enum station_info_bitrate_flags
+ * @txrate_mcs: MCS index of a 802.11n transmission, see
+ *  &enum station_info_bitrate_flags
  */
 struct station_info {
 	u32 filled;
@@ -200,6 +228,10 @@ struct station_info {
 	u16 llid;
 	u16 plid;
 	u8 plink_state;
+	u8 signal;
+	u16 txrate_total;
+	u8 txrate_flags;
+	u8 txrate_mcs;
 };
 
 /**
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 7a7a6c1..3567cd9 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -304,18 +304,65 @@ static int ieee80211_config_default_key(struct wiphy *wiphy,
 	return 0;
 }
 
+static u16 sta_get_80211n_bitrate(struct ieee80211_tx_rate *rate)
+{
+	int modulation = rate->idx & 7;
+	int streams = rate->idx >> 3;
+
+	int bitrate = (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) ? 13500000 : 6500000;
+
+	if (modulation < 4)
+		bitrate *= (modulation + 1);
+	else if (modulation == 4)
+		bitrate *= (modulation + 2);
+	else
+		bitrate *= (modulation + 3);
+
+	bitrate *= streams;
+
+	if (rate->flags & IEEE80211_TX_RC_SHORT_GI)
+		bitrate = (bitrate * 10) / 9;
+
+	return (bitrate + 50000) / 100000; // do NOT just round down
+}
+
 static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
 {
 	struct ieee80211_sub_if_data *sdata = sta->sdata;
 
 	sinfo->filled = STATION_INFO_INACTIVE_TIME |
 			STATION_INFO_RX_BYTES |
-			STATION_INFO_TX_BYTES;
+			STATION_INFO_TX_BYTES |
+			STATION_INFO_RX_BITRATE |
+			STATION_INFO_TX_BITRATE;
 
 	sinfo->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx);
 	sinfo->rx_bytes = sta->rx_bytes;
 	sinfo->tx_bytes = sta->tx_bytes;
 
+	if (sta->local->hw.flags & IEEE80211_HW_SIGNAL_DBM) {
+		sinfo->filled |= STATION_INFO_SIGNAL;
+		sinfo->signal = sta->last_signal;
+	}
+
+	sinfo->txrate_flags = 0;
+	if (sta->last_tx_rate.flags & IEEE80211_TX_RC_MCS)
+		sinfo->txrate_flags |= STATION_INFO_BITRATE_MCS;
+	if (sta->last_tx_rate.flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
+		sinfo->txrate_flags |= STATION_INFO_BITRATE_40_MHZ_WIDTH;
+	if (sta->last_tx_rate.flags & IEEE80211_TX_RC_SHORT_GI)
+		sinfo->txrate_flags |= STATION_INFO_BITRATE_SHORT_GI;
+
+	if (!(sta->last_tx_rate.flags & IEEE80211_TX_RC_MCS)) {
+		struct ieee80211_supported_band *sband;
+		sband = sta->local->hw.wiphy->bands[sta->local->hw.conf.channel->band];
+		sinfo->txrate_total = sband->bitrates[sta->last_tx_rate.idx].bitrate;
+	}
+	else {
+		sinfo->txrate_total = sta_get_80211n_bitrate(&sta->last_tx_rate);
+		sinfo->txrate_mcs = sta->last_tx_rate.idx;
+	}
+
 	if (ieee80211_vif_is_mesh(&sdata->vif)) {
 #ifdef CONFIG_MAC80211_MESH
 		sinfo->filled |= STATION_INFO_LLID |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 59f356a..84922b0 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -727,8 +727,9 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
 	if (rx->sdata->vif.type == NL80211_IFTYPE_ADHOC) {
 		u8 *bssid = ieee80211_get_bssid(hdr, rx->skb->len,
 						NL80211_IFTYPE_ADHOC);
-		if (compare_ether_addr(bssid, rx->sdata->u.sta.bssid) == 0)
+		if (compare_ether_addr(bssid, rx->sdata->u.sta.bssid) == 0) {
 			sta->last_rx = jiffies;
+		}
 	} else
 	if (!is_multicast_ether_addr(hdr->addr1) ||
 	    rx->sdata->vif.type == NL80211_IFTYPE_STATION) {
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 9caee60..197dc4d 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -16,6 +16,7 @@
 #include <linux/netlink.h>
 #include <net/genetlink.h>
 #include <net/cfg80211.h>
+#include <net/mac80211.h>
 #include "core.h"
 #include "nl80211.h"
 #include "reg.h"
@@ -1084,7 +1085,7 @@ static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
 				u8 *mac_addr, struct station_info *sinfo)
 {
 	void *hdr;
-	struct nlattr *sinfoattr;
+	struct nlattr *sinfoattr, *txrate;
 
 	hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_STATION);
 	if (!hdr)
@@ -1114,7 +1115,27 @@ static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
 	if (sinfo->filled & STATION_INFO_PLINK_STATE)
 		NLA_PUT_U8(msg, NL80211_STA_INFO_PLINK_STATE,
 			    sinfo->plink_state);
+	if (sinfo->filled & STATION_INFO_SIGNAL)
+		NLA_PUT_U8(msg, NL80211_STA_INFO_SIGNAL,
+			   sinfo->signal);
+	if (sinfo->filled & STATION_INFO_TX_BITRATE) {
+		txrate = nla_nest_start(msg, NL80211_STA_INFO_TX_BITRATE);
+		if (!txrate)
+			goto nla_put_failure;
+
+		NLA_PUT_U16(msg, NL80211_STA_INFO_RATE_TOTAL,
+			    sinfo->txrate_total);
 
+		if (sinfo->txrate_flags & STATION_INFO_BITRATE_MCS)
+			NLA_PUT_U16(msg, NL80211_STA_INFO_RATE_MCS,
+				    sinfo->txrate_mcs);
+		if (sinfo->txrate_flags & STATION_INFO_BITRATE_40_MHZ_WIDTH)
+			NLA_PUT_FLAG(msg, NL80211_STA_INFO_RATE_40_MHZ_WIDTH);
+		if (sinfo->txrate_flags & STATION_INFO_BITRATE_SHORT_GI)
+			NLA_PUT_FLAG(msg, NL80211_STA_INFO_RATE_SHORT_GI);
+
+		nla_nest_end(msg, txrate);
+	}
 	nla_nest_end(msg, sinfoattr);
 
 	return genlmsg_end(msg, hdr);

[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 197 bytes --]

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

* Re: RFC Patch v2: Add signal strength to nl80211station info
  2008-12-06 14:10                                 ` Henning Rogge
  2008-12-06 14:43                                   ` Henning Rogge
@ 2008-12-06 14:51                                   ` Johannes Berg
  2008-12-06 15:03                                     ` Henning Rogge
  1 sibling, 1 reply; 66+ messages in thread
From: Johannes Berg @ 2008-12-06 14:51 UTC (permalink / raw)
  To: Henning Rogge
  Cc: Henning Rogge, Luis R. Rodriguez, Luis Rodriguez,
	Marcel Holtmann, linux-wireless, nbd

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

On Sat, 2008-12-06 at 15:10 +0100, Henning Rogge wrote:
> Okay, here is v6 of my patch... feel free to rip it apart. ;)

Heh. Please inline patches, makes it much easier.

>  /**
> + * enum nl80211_sta_info_rate - station information about bitrate
> + *
> + * These attribute types are used with %NL80211_STA_INFO_TXRATE
> + * when getting information about the bitrate of a station.
> + *
> + * @__NL80211_STA_INFO_RATE_INVALID: attribute number 0 is reserved
> + * @NL80211_STA_INFO_RATE_TOTAL: total bitrate (u16, 100kbit/s)
> + * @NL80211_STA_INFO_RATE_MCS: mcs index for 802.11n (u8)
> + * @NL80211_STA_INFO_RATE_40_MHZ_WIDTH: 40 Mhz dualchannel bitrate
> + * @NL80211_STA_INFO_RATE_SHORT_GI: 400ns guard interval
> + */
> +enum nl80211_sta_info_rate {
> +       __NL80211_STA_INFO_RATE_INVALID,
> +       NL80211_STA_INFO_RATE_TOTAL,
> +       NL80211_STA_INFO_RATE_MCS,
> +       NL80211_STA_INFO_RATE_40_MHZ_WIDTH,
> +       NL80211_STA_INFO_RATE_SHORT_GI,
> +
> +       /* keep last */
> +       __NL80211_STA_INFO_RATE_AFTER_LAST,
> +       NL80211_STA_INFO_RATE_MAX = __NL80211_STA_INFO_RATE_AFTER_LAST - 1
> +};

I'd drop the _STA_ part from these and do RATE_INFO_... since we may end
up using these for other things potentially. Not sure we will, but who
knows. I could imagine using it to fix a transmit rate, for example, and
then it wouldn't necessarily be per station.

> + * @NL80211_STA_INFO_SIGNAL: signal strength of last received package (u8, dBm)

packet, or, more accurately, PPDU I guess

> + * @NL80211_STA_INFO_TX_BITRATE: current unicast tx rate, nested attribute
> + *  containing info as possible, see &enum nl80211_sta_info_txrate.

Please indent with a tab here

> + * @STATION_INFO_RX_BITRATE: @rx_bitrate filled
> + * @STATION_INFO_TX_BITRATE: @tx_bitrate fields are filled
> + *  (tx_bitrate, tx_bitrate_flags and tx_bitrate_mcs)
>   */
>  enum station_info_flags {
>         STATION_INFO_INACTIVE_TIME      = 1<<0,
> @@ -177,6 +181,25 @@ enum station_info_flags {
>         STATION_INFO_LLID               = 1<<3,
>         STATION_INFO_PLID               = 1<<4,
>         STATION_INFO_PLINK_STATE        = 1<<5,
> +       STATION_INFO_SIGNAL             = 1<<6,
> +       STATION_INFO_RX_BITRATE         = 1<<7,

RX bitrate?

> +/**
> + * enum station_info_rate_flags - station transmission rate flags
> + *
> + * Used by the driver to indicate the specific rate transmission
> + * type for 802.11n transmissions.
> + *
> + * @STATION_INFO_BITRATE_MCS: @tx_bitrate_mcs filled
> + * @STATION_INFO_BITRATE_40_MHZ_WIDTH: 40 Mhz width transmission
> + * @STATION_INFO_BITRATE_SHORT_GI: 400ns guard interval
> + */
> +enum station_info_rate_flags {
> +       STATION_INFO_BITRATE_MCS                = 1<<0,
> +       STATION_INFO_BITRATE_40_MHZ_WIDTH       = 1<<1,
> +       STATION_INFO_BITRATE_SHORT_GI           = 1<<2,
>  };

Same here as the first comment, this is rate specific, so I'd call these
BITRATE_* or something like that.
 
>  /**
> @@ -191,6 +214,11 @@ enum station_info_flags {
>   * @llid: mesh local link id
>   * @plid: mesh peer link id
>   * @plink_state: mesh peer link state
> + * @signal: signal strength of last received package in dBm
> + * @txrate_total: current unicast bitrate to this station in 100 kbit/sec
> + * @txrate_flags: bitflag of flags from &enum station_info_bitrate_flags
> + * @txrate_mcs: MCS index of a 802.11n transmission, see
> + *  &enum station_info_bitrate_flags
>   */
>  struct station_info {
>         u32 filled;
> @@ -200,6 +228,10 @@ struct station_info {
>         u16 llid;
>         u16 plid;
>         u8 plink_state;
> +       u8 signal;
> +       u16 txrate_total;
> +       u8 txrate_flags;
> +       u8 txrate_mcs;

can you please move the rate parts into a new struct, so we can use
tx.flags, tx.mcs etc. and later just need to add a second instance of
the struct for rx
 
> +static u16 sta_get_80211n_bitrate(struct ieee80211_tx_rate *rate)
> +{
> +       int modulation = rate->idx & 7;
> +       int streams = rate->idx >> 3;
> +
> +       int bitrate = (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) ? 13500000 : 6500000;
> +
> +       if (modulation < 4)
> +               bitrate *= (modulation + 1);
> +       else if (modulation == 4)
> +               bitrate *= (modulation + 2);
> +       else
> +               bitrate *= (modulation + 3);
> +
> +       bitrate *= streams;
> +
> +       if (rate->flags & IEEE80211_TX_RC_SHORT_GI)
> +               bitrate = (bitrate * 10) / 9;
> +
> +       return (bitrate + 50000) / 100000; // do NOT just round down
> +}

Don't use // comments please, see Documentation/CodingStyle.

Also, if we really really need this information (I still don't see why
the kernel has to calculate it) then it should be in cfg80211 not
mac80211 so other drivers could potentially make use of it. Personally,
I'd just leave it out though.

>         sinfo->filled = STATION_INFO_INACTIVE_TIME |
>                         STATION_INFO_RX_BYTES |
> -                       STATION_INFO_TX_BYTES;
> +                       STATION_INFO_TX_BYTES |
> +                       STATION_INFO_RX_BITRATE |
> +                       STATION_INFO_TX_BITRATE;

RX?

> --- a/net/mac80211/rx.c
> +++ b/net/mac80211/rx.c
> @@ -727,8 +727,9 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
>         if (rx->sdata->vif.type == NL80211_IFTYPE_ADHOC) {
>                 u8 *bssid = ieee80211_get_bssid(hdr, rx->skb->len,
>                                                 NL80211_IFTYPE_ADHOC);
> -               if (compare_ether_addr(bssid, rx->sdata->u.sta.bssid) == 0)
> +               if (compare_ether_addr(bssid, rx->sdata->u.sta.bssid) == 0) {
>                         sta->last_rx = jiffies;
> +               }
>         } else
>         if (!is_multicast_ether_addr(hdr->addr1) ||
>             rx->sdata->vif.type == NL80211_IFTYPE_STATION) {

That looks unintended

> diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
> index 9caee60..197dc4d 100644
> --- a/net/wireless/nl80211.c
> +++ b/net/wireless/nl80211.c
> @@ -16,6 +16,7 @@
>  #include <linux/netlink.h>
>  #include <net/genetlink.h>
>  #include <net/cfg80211.h>
> +#include <net/mac80211.h>

Ahem. Please observe the layering, cfg80211 and nl80211 are strictly
below mac80211.


I'd rename _TOTAL to _LEGACY and remove the calculation for MCS rates,
that way it's obviously clear what you're getting in userland.

johannes

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

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

* Re: RFC Patch v2: Add signal strength to nl80211station info
  2008-12-06 14:51                                   ` Johannes Berg
@ 2008-12-06 15:03                                     ` Henning Rogge
  2008-12-06 15:46                                       ` Henning Rogge
  2008-12-06 15:48                                       ` RFC Patch v2: Add signal strength " Johannes Berg
  0 siblings, 2 replies; 66+ messages in thread
From: Henning Rogge @ 2008-12-06 15:03 UTC (permalink / raw)
  To: Johannes Berg
  Cc: Henning Rogge, Luis R. Rodriguez, Luis Rodriguez,
	Marcel Holtmann, linux-wireless, nbd

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

On Saturday 06 December 2008 15:51:20 Johannes Berg wrote:
> > Okay, here is v6 of my patch... feel free to rip it apart. ;)
>
> Heh. Please inline patches, makes it much easier.
Resend it inlined... but you were a little bit too fast... ;)

> I'd drop the _STA_ part from these and do RATE_INFO_... since we may end
> up using these for other things potentially. Not sure we will, but who
> knows. I could imagine using it to fix a transmit rate, for example, and
> then it wouldn't necessarily be per station.
Okay, will be done in v7

> > + * @NL80211_STA_INFO_SIGNAL: signal strength of last received package
> > (u8, dBm)
>
> packet, or, more accurately, PPDU I guess
ok.

> > + * @NL80211_STA_INFO_TX_BITRATE: current unicast tx rate, nested
> > attribute + *  containing info as possible, see &enum
> > nl80211_sta_info_txrate.
>
> Please indent with a tab here

> > + * @STATION_INFO_RX_BITRATE: @rx_bitrate filled
> > + * @STATION_INFO_TX_BITRATE: @tx_bitrate fields are filled
> > + *  (tx_bitrate, tx_bitrate_flags and tx_bitrate_mcs)
> >   */
> >  enum station_info_flags {
> >         STATION_INFO_INACTIVE_TIME      = 1<<0,
> > @@ -177,6 +181,25 @@ enum station_info_flags {
> >         STATION_INFO_LLID               = 1<<3,
> >         STATION_INFO_PLID               = 1<<4,
> >         STATION_INFO_PLINK_STATE        = 1<<5,
> > +       STATION_INFO_SIGNAL             = 1<<6,
> > +       STATION_INFO_RX_BITRATE         = 1<<7,
>
> RX bitrate?
Okay, it seems I missed one place to remove the RX one... thought I had got 
all of them.

> > +/**
> > + * enum station_info_rate_flags - station transmission rate flags
> > + *
> > + * Used by the driver to indicate the specific rate transmission
> > + * type for 802.11n transmissions.
> > + *
> > + * @STATION_INFO_BITRATE_MCS: @tx_bitrate_mcs filled
> > + * @STATION_INFO_BITRATE_40_MHZ_WIDTH: 40 Mhz width transmission
> > + * @STATION_INFO_BITRATE_SHORT_GI: 400ns guard interval
> > + */
> > +enum station_info_rate_flags {
> > +       STATION_INFO_BITRATE_MCS                = 1<<0,
> > +       STATION_INFO_BITRATE_40_MHZ_WIDTH       = 1<<1,
> > +       STATION_INFO_BITRATE_SHORT_GI           = 1<<2,
> >  };
>
> Same here as the first comment, this is rate specific, so I'd call these
> BITRATE_* or something like that.
okay.

> >  /**
> > @@ -191,6 +214,11 @@ enum station_info_flags {
> >   * @llid: mesh local link id
> >   * @plid: mesh peer link id
> >   * @plink_state: mesh peer link state
> > + * @signal: signal strength of last received package in dBm
> > + * @txrate_total: current unicast bitrate to this station in 100
> > kbit/sec + * @txrate_flags: bitflag of flags from &enum
> > station_info_bitrate_flags + * @txrate_mcs: MCS index of a 802.11n
> > transmission, see
> > + *  &enum station_info_bitrate_flags
> >   */
> >  struct station_info {
> >         u32 filled;
> > @@ -200,6 +228,10 @@ struct station_info {
> >         u16 llid;
> >         u16 plid;
> >         u8 plink_state;
> > +       u8 signal;
> > +       u16 txrate_total;
> > +       u8 txrate_flags;
> > +       u8 txrate_mcs;
>
> can you please move the rate parts into a new struct, so we can use
> tx.flags, tx.mcs etc. and later just need to add a second instance of
> the struct for rx

struct bitrate_info ?
or maybe
struct cfg80211_bitrate_info ?

> > +static u16 sta_get_80211n_bitrate(struct ieee80211_tx_rate *rate)
> > +{
> > +       int modulation = rate->idx & 7;
> > +       int streams = rate->idx >> 3;
> > +
> > +       int bitrate = (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) ?
> > 13500000 : 6500000; +
> > +       if (modulation < 4)
> > +               bitrate *= (modulation + 1);
> > +       else if (modulation == 4)
> > +               bitrate *= (modulation + 2);
> > +       else
> > +               bitrate *= (modulation + 3);
> > +
> > +       bitrate *= streams;
> > +
> > +       if (rate->flags & IEEE80211_TX_RC_SHORT_GI)
> > +               bitrate = (bitrate * 10) / 9;
> > +
> > +       return (bitrate + 50000) / 100000; // do NOT just round down
> > +}
>
> Don't use // comments please, see Documentation/CodingStyle.
Copypasta error from the "pseudocode", sorry.

> Also, if we really really need this information (I still don't see why
> the kernel has to calculate it) then it should be in cfg80211 not
> mac80211 so other drivers could potentially make use of it. Personally,
> I'd just leave it out though.
Hmm... is "cfg.c" not part of cfg80211 ?

> >         sinfo->filled = STATION_INFO_INACTIVE_TIME |
> >                         STATION_INFO_RX_BYTES |
> > -                       STATION_INFO_TX_BYTES;
> > +                       STATION_INFO_TX_BYTES |
> > +                       STATION_INFO_RX_BITRATE |
> > +                       STATION_INFO_TX_BITRATE;
>
> RX?
Another one... I think I will have to post a v7 patch this weekend...

> > --- a/net/mac80211/rx.c
> > +++ b/net/mac80211/rx.c
> > @@ -727,8 +727,9 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data
> > *rx) if (rx->sdata->vif.type == NL80211_IFTYPE_ADHOC) {
> >                 u8 *bssid = ieee80211_get_bssid(hdr, rx->skb->len,
> >                                                 NL80211_IFTYPE_ADHOC);
> > -               if (compare_ether_addr(bssid, rx->sdata->u.sta.bssid) ==
> > 0) +               if (compare_ether_addr(bssid, rx->sdata->u.sta.bssid)
> > == 0) { sta->last_rx = jiffies;
> > +               }
> >         } else
> >         if (!is_multicast_ether_addr(hdr->addr1) ||
> >             rx->sdata->vif.type == NL80211_IFTYPE_STATION) {
>
> That looks unintended
Yes.. I removed the "else" part for the rx_rate, but left the {} there.

> > diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
> > index 9caee60..197dc4d 100644
> > --- a/net/wireless/nl80211.c
> > +++ b/net/wireless/nl80211.c
> > @@ -16,6 +16,7 @@
> >  #include <linux/netlink.h>
> >  #include <net/genetlink.h>
> >  #include <net/cfg80211.h>
> > +#include <net/mac80211.h>
>
> Ahem. Please observe the layering, cfg80211 and nl80211 are strictly
> below mac80211.
>
>
> I'd rename _TOTAL to _LEGACY and remove the calculation for MCS rates,
> that way it's obviously clear what you're getting in userland.
We need the "total bitrate" for 802.11abg rates. They have no mcs rates.
The "legacy index" for non 802.11n bitrates points to a hw specific "band" 
array, so I don't think we can export it to userspace as an index.

Henning

[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 197 bytes --]

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

* Re: RFC Patch v2: Add signal strength to nl80211station info
  2008-12-06 15:03                                     ` Henning Rogge
@ 2008-12-06 15:46                                       ` Henning Rogge
  2008-12-06 15:59                                         ` Johannes Berg
  2008-12-06 15:48                                       ` RFC Patch v2: Add signal strength " Johannes Berg
  1 sibling, 1 reply; 66+ messages in thread
From: Henning Rogge @ 2008-12-06 15:46 UTC (permalink / raw)
  To: Johannes Berg
  Cc: Henning Rogge, Luis R. Rodriguez, Luis Rodriguez,
	Marcel Holtmann, linux-wireless, nbd

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

On Saturday 06 December 2008 16:03:16 Henning Rogge wrote:
> > I'd rename _TOTAL to _LEGACY and remove the calculation for MCS rates,
> > that way it's obviously clear what you're getting in userland.
Okay, after reading your mail a second time I understood you... 

I think with removing the total bitrate for 802.11n we will just make the 
userspace interface more complex. You will have to look at four different 
things (flags, MCS, guard interval, legacy) just to get the bitrate, which 
will be the typical information the user wants to know. Is there anything 
nl80211 will gain if we don't put this value inside for all 802.11 ? We cannot 
drop it because of 802.11abg, so why not fill it with useful data ?

Henning

[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 197 bytes --]

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

* Re: RFC Patch v2: Add signal strength to nl80211station info
  2008-12-06 15:03                                     ` Henning Rogge
  2008-12-06 15:46                                       ` Henning Rogge
@ 2008-12-06 15:48                                       ` Johannes Berg
  1 sibling, 0 replies; 66+ messages in thread
From: Johannes Berg @ 2008-12-06 15:48 UTC (permalink / raw)
  To: Henning Rogge
  Cc: Henning Rogge, Luis R. Rodriguez, Luis Rodriguez,
	Marcel Holtmann, linux-wireless, nbd

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

On Sat, 2008-12-06 at 16:03 +0100, Henning Rogge wrote:

> > can you please move the rate parts into a new struct, so we can use
> > tx.flags, tx.mcs etc. and later just need to add a second instance of
> > the struct for rx
> 
> struct bitrate_info ?
> or maybe
> struct cfg80211_bitrate_info ?

Either one is fine I guess.

> > Also, if we really really need this information (I still don't see why
> > the kernel has to calculate it) then it should be in cfg80211 not
> > mac80211 so other drivers could potentially make use of it. Personally,
> > I'd just leave it out though.

> Hmm... is "cfg.c" not part of cfg80211 ?

No, cfg.c is part of mac80211, it's mac80211's code to interact with
cfg80211, it won't be called for non-mac80211 drivers.

> We need the "total bitrate" for 802.11abg rates. They have no mcs rates.
> The "legacy index" for non 802.11n bitrates points to a hw specific "band" 
> array, so I don't think we can export it to userspace as an index.

But we can name it _legacy and put the bitrate there in units of
100kbps, and leave it out for MCS rates then.

johannes

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

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

* Re: RFC Patch v2: Add signal strength to nl80211station info
  2008-12-06 15:46                                       ` Henning Rogge
@ 2008-12-06 15:59                                         ` Johannes Berg
  2008-12-06 16:08                                           ` Henning Rogge
  2008-12-06 20:46                                           ` Luis R. Rodriguez
  0 siblings, 2 replies; 66+ messages in thread
From: Johannes Berg @ 2008-12-06 15:59 UTC (permalink / raw)
  To: Henning Rogge
  Cc: Henning Rogge, Luis R. Rodriguez, Luis Rodriguez,
	Marcel Holtmann, linux-wireless, nbd

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

On Sat, 2008-12-06 at 16:46 +0100, Henning Rogge wrote:
> On Saturday 06 December 2008 16:03:16 Henning Rogge wrote:
> > > I'd rename _TOTAL to _LEGACY and remove the calculation for MCS rates,
> > > that way it's obviously clear what you're getting in userland.
> Okay, after reading your mail a second time I understood you... 
> 
> I think with removing the total bitrate for 802.11n we will just make the 
> userspace interface more complex. You will have to look at four different 
> things (flags, MCS, guard interval, legacy) just to get the bitrate, which 
> will be the typical information the user wants to know. Is there anything 
> nl80211 will gain if we don't put this value inside for all 802.11 ? We cannot 
> drop it because of 802.11abg, so why not fill it with useful data ?

For one, I'm a bit concerned that the calculation is fairly complex, and
may not always be necessary; especially divisions can be expensive on
some CPUs.

Also, there are duplicate numbers possible, so just the pure bitrate
will _not_ actually be "the typical information" because it's not
specific enough, when debugging, for example, you will probably need to
know whether it's short-gi or not.

johannes

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

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

* Re: RFC Patch v2: Add signal strength to nl80211station info
  2008-12-06 15:59                                         ` Johannes Berg
@ 2008-12-06 16:08                                           ` Henning Rogge
  2008-12-06 20:46                                           ` Luis R. Rodriguez
  1 sibling, 0 replies; 66+ messages in thread
From: Henning Rogge @ 2008-12-06 16:08 UTC (permalink / raw)
  To: Johannes Berg
  Cc: Henning Rogge, Luis R. Rodriguez, Luis Rodriguez,
	Marcel Holtmann, linux-wireless, nbd

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

On Saturday 06 December 2008 16:59:32 Johannes Berg wrote:
> For one, I'm a bit concerned that the calculation is fairly complex, and
> may not always be necessary; especially divisions can be expensive on
> some CPUs.
What if I push the calculation into nl80211.c, so it will be only called when 
the a userspace process requests the station info ? This would mean the 
calculation is not done at all until someone needs the rate info.

> Also, there are duplicate numbers possible, so just the pure bitrate
> will _not_ actually be "the typical information" because it's not
> specific enough, when debugging, for example, you will probably need to
> know whether it's short-gi or not.
Don't you think the normal nl80211 use will just be a display of "how fast are 
we doing at the moment" ? Most applications don't even need to set a rate, 
they just want to show the user some feedback.

Henning


[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 197 bytes --]

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

* Re: RFC Patch v2: Add signal strength to nl80211station info
  2008-12-06 15:59                                         ` Johannes Berg
  2008-12-06 16:08                                           ` Henning Rogge
@ 2008-12-06 20:46                                           ` Luis R. Rodriguez
  2008-12-07 17:32                                             ` Henning Rogge
  1 sibling, 1 reply; 66+ messages in thread
From: Luis R. Rodriguez @ 2008-12-06 20:46 UTC (permalink / raw)
  To: Johannes Berg
  Cc: Henning Rogge, Henning Rogge, Luis Rodriguez, Marcel Holtmann,
	linux-wireless, nbd

On Sat, Dec 6, 2008 at 7:59 AM, Johannes Berg <johannes@sipsolutions.net> wrote:
> On Sat, 2008-12-06 at 16:46 +0100, Henning Rogge wrote:
>> On Saturday 06 December 2008 16:03:16 Henning Rogge wrote:
>> > > I'd rename _TOTAL to _LEGACY and remove the calculation for MCS rates,
>> > > that way it's obviously clear what you're getting in userland.
>> Okay, after reading your mail a second time I understood you...
>>
>> I think with removing the total bitrate for 802.11n we will just make the
>> userspace interface more complex. You will have to look at four different
>> things (flags, MCS, guard interval, legacy) just to get the bitrate, which
>> will be the typical information the user wants to know. Is there anything
>> nl80211 will gain if we don't put this value inside for all 802.11 ? We cannot
>> drop it because of 802.11abg, so why not fill it with useful data ?
>
> For one, I'm a bit concerned that the calculation is fairly complex, and
> may not always be necessary; especially divisions can be expensive on
> some CPUs.
>
> Also, there are duplicate numbers possible, so just the pure bitrate
> will _not_ actually be "the typical information" because it's not
> specific enough, when debugging, for example, you will probably need to
> know whether it's short-gi or not.

Aren't we providing that *as well*?

  Luis

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

* Re: RFC Patch v2: Add signal strength to nl80211station info
  2008-12-06 20:46                                           ` Luis R. Rodriguez
@ 2008-12-07 17:32                                             ` Henning Rogge
  2008-12-07 17:39                                               ` Johannes Berg
  0 siblings, 1 reply; 66+ messages in thread
From: Henning Rogge @ 2008-12-07 17:32 UTC (permalink / raw)
  To: Luis R. Rodriguez
  Cc: Johannes Berg, Henning Rogge, Luis Rodriguez, Marcel Holtmann,
	linux-wireless, nbd


[-- Attachment #1.1: Type: text/plain, Size: 9724 bytes --]

On Saturday 06 December 2008 21:46:13 Luis R. Rodriguez wrote:
> On Sat, Dec 6, 2008 at 7:59 AM, Johannes Berg <johannes@sipsolutions.net> 
wrote:
> > Also, there are duplicate numbers possible, so just the pure bitrate
> > will _not_ actually be "the typical information" because it's not
> > specific enough, when debugging, for example, you will probably need to
> > know whether it's short-gi or not.
>
> Aren't we providing that *as well*?
I think the suggestion is to remove the total/legacy bitrate for 802.11n 
completely from the nl80211 station_info. Which I still think is not a good 
idea. This way we force any  application displaying the bitrate to check for 
several cases, know about the 802.11n table, ...
I think it's funny that we have the "total bitrate" information available on 
driver level but translate it into the mcs index with the help of tables... 
and assume that userspace knows about the tables.

But here is the next version of my patch, this one without the "total 
bandwith" for 802.11n... I can easily put it back later.

Changes since v1:
- removed noise and quality from station info in NL80211
- added bandwith to station info in NL80211
- changed name of patch file to nl80211ext_v2.patch
  
Changes since v2:
- added kernel comment lines for new fields/enums
- changed name of "bandwith" field to tx_bitrate

Changes since v3:
- added rx_bitrate to station info and sta_info
- remember bitrate of last received unicast packet to this station
- decode 802.11n MCS index for nl80211
  (maybe this should be ported to WEXT too ?)

Changes since v4:
- added tx_bitrate_flags adn tx_bitrate_mcs field to station info
- added flags for 40Mhz and small guard interval to NL80211 station info
- added mcs field to NL80211 station info

Changes since v5:
- remove rx_bitrate from patch until we get a sane way to learn the details of  
received 802.11n packages
-replace 802.11n bitrate arrays with calculation based on basic rates
- pushed txrate nl80211 stationinfo into nested attribute
- created station_info_rate_flags enum to save bitrate flags in station_info
- cleanup of kerneldoc

Changes since v6:
- removed mcs index to bitrate conversion
- push station info bitrate into substructure
- renamed "total" bitrate into "legacy"
- some code cleanup

Henning

-------------------
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index 04d4516..26e68b9 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -425,6 +425,30 @@ enum nl80211_sta_flags {
 };
 
 /**
+ * enum nl80211_sta_info_rate - station information about bitrate
+ *
+ * These attribute types are used with %NL80211_STA_INFO_TXRATE
+ * when getting information about the bitrate of a station.
+ *
+ * @__NL80211_STA_INFO_RATE_INVALID: attribute number 0 is reserved
+ * @NL80211_STA_INFO_RATE_LEGACY: bitrate for 802.11abg (u16, 100kbit/s)
+ * @NL80211_STA_INFO_RATE_MCS: mcs index for 802.11n (u8)
+ * @NL80211_STA_INFO_RATE_40_MHZ_WIDTH: 40 Mhz dualchannel bitrate
+ * @NL80211_STA_INFO_RATE_SHORT_GI: 400ns guard interval
+ */
+enum nl80211_sta_info_rate {
+	__NL80211_STA_INFO_RATE_INVALID,
+	NL80211_STA_INFO_RATE_LEGACY,
+	NL80211_STA_INFO_RATE_MCS,
+	NL80211_STA_INFO_RATE_40_MHZ_WIDTH,
+	NL80211_STA_INFO_RATE_SHORT_GI,
+
+	/* keep last */
+	__NL80211_STA_INFO_RATE_AFTER_LAST,
+	NL80211_STA_INFO_RATE_MAX = __NL80211_STA_INFO_RATE_AFTER_LAST - 1
+};
+
+/**
  * enum nl80211_sta_info - station information
  *
  * These attribute types are used with %NL80211_ATTR_STA_INFO
@@ -436,6 +460,9 @@ enum nl80211_sta_flags {
  * @NL80211_STA_INFO_TX_BYTES: total transmitted bytes (u32, to this station)
  * @__NL80211_STA_INFO_AFTER_LAST: internal
  * @NL80211_STA_INFO_MAX: highest possible station info attribute
+ * @NL80211_STA_INFO_SIGNAL: signal strength of last received PPDU (u8, dBm)
+ * @NL80211_STA_INFO_TX_BITRATE: current unicast tx rate, nested attribute
+ * 	containing info as possible, see &enum nl80211_sta_info_txrate.
  */
 enum nl80211_sta_info {
 	__NL80211_STA_INFO_INVALID,
@@ -445,6 +472,8 @@ enum nl80211_sta_info {
 	NL80211_STA_INFO_LLID,
 	NL80211_STA_INFO_PLID,
 	NL80211_STA_INFO_PLINK_STATE,
+	NL80211_STA_INFO_SIGNAL,
+	NL80211_STA_INFO_TX_BITRATE,
 
 	/* keep last */
 	__NL80211_STA_INFO_AFTER_LAST,
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index a0c0bf1..d9ce51e 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -169,6 +169,9 @@ struct station_parameters {
  * @STATION_INFO_LLID: @llid filled
  * @STATION_INFO_PLID: @plid filled
  * @STATION_INFO_PLINK_STATE: @plink_state filled
+ * @STATION_INFO_SIGNAL: @signal filled
+ * @STATION_INFO_TX_BITRATE: @tx_bitrate fields are filled
+ *  (tx_bitrate, tx_bitrate_flags and tx_bitrate_mcs)
  */
 enum station_info_flags {
 	STATION_INFO_INACTIVE_TIME	= 1<<0,
@@ -177,6 +180,39 @@ enum station_info_flags {
 	STATION_INFO_LLID		= 1<<3,
 	STATION_INFO_PLID		= 1<<4,
 	STATION_INFO_PLINK_STATE	= 1<<5,
+	STATION_INFO_SIGNAL		= 1<<6,
+	STATION_INFO_TX_BITRATE		= 1<<7,
+};
+
+/**
+ * enum station_info_rate_flags - bitrate info flags
+ *
+ * Used by the driver to indicate the specific rate transmission
+ * type for 802.11n transmissions.
+ *
+ * @RATE_INFO_FLAGS_MCS: @tx_bitrate_mcs filled
+ * @RATE_INFO_FLAGS_40_MHZ_WIDTH: 40 Mhz width transmission
+ * @RATE_INFO_FLAGS_SHORT_GI: 400ns guard interval
+ */
+enum rate_info_flags {
+	RATE_INFO_FLAGS_MCS		= 1<<0,
+	RATE_INFO_FLAGS_40_MHZ_WIDTH	= 1<<1,
+	RATE_INFO_FLAGS_SHORT_GI	= 1<<2,
+};
+
+/**
+ * struct rate_info - bitrate information
+ *
+ * Information about a receiving or transmitting bitrate
+ *
+ * @flags: bitflag of flags from &enum rate_info_flags
+ * @mcs: mcs index if struct describes a 802.11n bitrate
+ * @legacy: bitrate in 100kbit/s for 802.11abg
+ */
+struct rate_info {
+	u8 flags;
+	u8 mcs;
+	u16 legacy;
 };
 
 /**
@@ -191,6 +227,8 @@ enum station_info_flags {
  * @llid: mesh local link id
  * @plid: mesh peer link id
  * @plink_state: mesh peer link state
+ * @signal: signal strength of last received package in dBm
+ * @txrate: current unicast bitrate to this station
  */
 struct station_info {
 	u32 filled;
@@ -200,6 +238,8 @@ struct station_info {
 	u16 llid;
 	u16 plid;
 	u8 plink_state;
+	u8 signal;
+	struct rate_info txrate;
 };
 
 /**
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 7a7a6c1..e6c2b7a 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -310,12 +310,35 @@ static void sta_set_sinfo(struct sta_info *sta, struct 
station_info *sinfo)
 
 	sinfo->filled = STATION_INFO_INACTIVE_TIME |
 			STATION_INFO_RX_BYTES |
-			STATION_INFO_TX_BYTES;
+			STATION_INFO_TX_BYTES |
+			STATION_INFO_TX_BITRATE;
 
 	sinfo->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx);
 	sinfo->rx_bytes = sta->rx_bytes;
 	sinfo->tx_bytes = sta->tx_bytes;
 
+	if (sta->local->hw.flags & IEEE80211_HW_SIGNAL_DBM) {
+		sinfo->filled |= STATION_INFO_SIGNAL;
+		sinfo->signal = sta->last_signal;
+	}
+
+	sinfo->txrate.flags = 0;
+	if (sta->last_tx_rate.flags & IEEE80211_TX_RC_MCS)
+		sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
+	if (sta->last_tx_rate.flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
+		sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
+	if (sta->last_tx_rate.flags & IEEE80211_TX_RC_SHORT_GI)
+		sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
+
+	if (!(sta->last_tx_rate.flags & IEEE80211_TX_RC_MCS)) {
+		struct ieee80211_supported_band *sband;
+		sband = sta->local->hw.wiphy->bands[sta->local->hw.conf.channel->band];
+		sinfo->txrate.legacy = sband->bitrates[sta->last_tx_rate.idx].bitrate;
+	}
+	else {
+		sinfo->txrate.mcs = sta->last_tx_rate.idx;
+	}
+
 	if (ieee80211_vif_is_mesh(&sdata->vif)) {
 #ifdef CONFIG_MAC80211_MESH
 		sinfo->filled |= STATION_INFO_LLID |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 9caee60..ced38a7 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -14,6 +14,7 @@
 #include <linux/nl80211.h>
 #include <linux/rtnetlink.h>
 #include <linux/netlink.h>
+#include <net/mac80211.h>
 #include <net/genetlink.h>
 #include <net/cfg80211.h>
 #include "core.h"
@@ -1084,7 +1085,7 @@ static int nl80211_send_station(struct sk_buff *msg, u32 
pid, u32 seq,
 				u8 *mac_addr, struct station_info *sinfo)
 {
 	void *hdr;
-	struct nlattr *sinfoattr;
+	struct nlattr *sinfoattr, *txrate;
 
 	hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_STATION);
 	if (!hdr)
@@ -1114,7 +1115,28 @@ static int nl80211_send_station(struct sk_buff *msg, 
u32 pid, u32 seq,
 	if (sinfo->filled & STATION_INFO_PLINK_STATE)
 		NLA_PUT_U8(msg, NL80211_STA_INFO_PLINK_STATE,
 			    sinfo->plink_state);
+	if (sinfo->filled & STATION_INFO_SIGNAL)
+		NLA_PUT_U8(msg, NL80211_STA_INFO_SIGNAL,
+			   sinfo->signal);
+	if (sinfo->filled & STATION_INFO_TX_BITRATE) {
+		txrate = nla_nest_start(msg, NL80211_STA_INFO_TX_BITRATE);
+		if (!txrate)
+			goto nla_put_failure;
+
 
+		if (!(sinfo->txrate.flags & RATE_INFO_FLAGS_MCS))
+			NLA_PUT_U16(msg, NL80211_STA_INFO_RATE_LEGACY,
+				    sinfo->txrate.legacy);
+		else
+			NLA_PUT_U16(msg, NL80211_STA_INFO_RATE_MCS,
+				    sinfo->txrate.mcs);
+		if (sinfo->txrate.flags & RATE_INFO_FLAGS_40_MHZ_WIDTH)
+			NLA_PUT_FLAG(msg, NL80211_STA_INFO_RATE_40_MHZ_WIDTH);
+		if (sinfo->txrate.flags & RATE_INFO_FLAGS_SHORT_GI)
+			NLA_PUT_FLAG(msg, NL80211_STA_INFO_RATE_SHORT_GI);
+
+		nla_nest_end(msg, txrate);
+	}
 	nla_nest_end(msg, sinfoattr);
 
 	return genlmsg_end(msg, hdr);


[-- Attachment #1.2: nl80211ext_v7.patch --]
[-- Type: text/x-patch, Size: 7337 bytes --]

diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index 04d4516..26e68b9 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -425,6 +425,30 @@ enum nl80211_sta_flags {
 };
 
 /**
+ * enum nl80211_sta_info_rate - station information about bitrate
+ *
+ * These attribute types are used with %NL80211_STA_INFO_TXRATE
+ * when getting information about the bitrate of a station.
+ *
+ * @__NL80211_STA_INFO_RATE_INVALID: attribute number 0 is reserved
+ * @NL80211_STA_INFO_RATE_LEGACY: bitrate for 802.11abg (u16, 100kbit/s)
+ * @NL80211_STA_INFO_RATE_MCS: mcs index for 802.11n (u8)
+ * @NL80211_STA_INFO_RATE_40_MHZ_WIDTH: 40 Mhz dualchannel bitrate
+ * @NL80211_STA_INFO_RATE_SHORT_GI: 400ns guard interval
+ */
+enum nl80211_sta_info_rate {
+	__NL80211_STA_INFO_RATE_INVALID,
+	NL80211_STA_INFO_RATE_LEGACY,
+	NL80211_STA_INFO_RATE_MCS,
+	NL80211_STA_INFO_RATE_40_MHZ_WIDTH,
+	NL80211_STA_INFO_RATE_SHORT_GI,
+
+	/* keep last */
+	__NL80211_STA_INFO_RATE_AFTER_LAST,
+	NL80211_STA_INFO_RATE_MAX = __NL80211_STA_INFO_RATE_AFTER_LAST - 1
+};
+
+/**
  * enum nl80211_sta_info - station information
  *
  * These attribute types are used with %NL80211_ATTR_STA_INFO
@@ -436,6 +460,9 @@ enum nl80211_sta_flags {
  * @NL80211_STA_INFO_TX_BYTES: total transmitted bytes (u32, to this station)
  * @__NL80211_STA_INFO_AFTER_LAST: internal
  * @NL80211_STA_INFO_MAX: highest possible station info attribute
+ * @NL80211_STA_INFO_SIGNAL: signal strength of last received PPDU (u8, dBm)
+ * @NL80211_STA_INFO_TX_BITRATE: current unicast tx rate, nested attribute
+ * 	containing info as possible, see &enum nl80211_sta_info_txrate.
  */
 enum nl80211_sta_info {
 	__NL80211_STA_INFO_INVALID,
@@ -445,6 +472,8 @@ enum nl80211_sta_info {
 	NL80211_STA_INFO_LLID,
 	NL80211_STA_INFO_PLID,
 	NL80211_STA_INFO_PLINK_STATE,
+	NL80211_STA_INFO_SIGNAL,
+	NL80211_STA_INFO_TX_BITRATE,
 
 	/* keep last */
 	__NL80211_STA_INFO_AFTER_LAST,
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index a0c0bf1..d9ce51e 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -169,6 +169,9 @@ struct station_parameters {
  * @STATION_INFO_LLID: @llid filled
  * @STATION_INFO_PLID: @plid filled
  * @STATION_INFO_PLINK_STATE: @plink_state filled
+ * @STATION_INFO_SIGNAL: @signal filled
+ * @STATION_INFO_TX_BITRATE: @tx_bitrate fields are filled
+ *  (tx_bitrate, tx_bitrate_flags and tx_bitrate_mcs)
  */
 enum station_info_flags {
 	STATION_INFO_INACTIVE_TIME	= 1<<0,
@@ -177,6 +180,39 @@ enum station_info_flags {
 	STATION_INFO_LLID		= 1<<3,
 	STATION_INFO_PLID		= 1<<4,
 	STATION_INFO_PLINK_STATE	= 1<<5,
+	STATION_INFO_SIGNAL		= 1<<6,
+	STATION_INFO_TX_BITRATE		= 1<<7,
+};
+
+/**
+ * enum station_info_rate_flags - bitrate info flags
+ *
+ * Used by the driver to indicate the specific rate transmission
+ * type for 802.11n transmissions.
+ *
+ * @RATE_INFO_FLAGS_MCS: @tx_bitrate_mcs filled
+ * @RATE_INFO_FLAGS_40_MHZ_WIDTH: 40 Mhz width transmission
+ * @RATE_INFO_FLAGS_SHORT_GI: 400ns guard interval
+ */
+enum rate_info_flags {
+	RATE_INFO_FLAGS_MCS		= 1<<0,
+	RATE_INFO_FLAGS_40_MHZ_WIDTH	= 1<<1,
+	RATE_INFO_FLAGS_SHORT_GI	= 1<<2,
+};
+
+/**
+ * struct rate_info - bitrate information
+ *
+ * Information about a receiving or transmitting bitrate
+ *
+ * @flags: bitflag of flags from &enum rate_info_flags
+ * @mcs: mcs index if struct describes a 802.11n bitrate
+ * @legacy: bitrate in 100kbit/s for 802.11abg
+ */
+struct rate_info {
+	u8 flags;
+	u8 mcs;
+	u16 legacy;
 };
 
 /**
@@ -191,6 +227,8 @@ enum station_info_flags {
  * @llid: mesh local link id
  * @plid: mesh peer link id
  * @plink_state: mesh peer link state
+ * @signal: signal strength of last received package in dBm
+ * @txrate: current unicast bitrate to this station
  */
 struct station_info {
 	u32 filled;
@@ -200,6 +238,8 @@ struct station_info {
 	u16 llid;
 	u16 plid;
 	u8 plink_state;
+	u8 signal;
+	struct rate_info txrate;
 };
 
 /**
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 7a7a6c1..e6c2b7a 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -310,12 +310,35 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
 
 	sinfo->filled = STATION_INFO_INACTIVE_TIME |
 			STATION_INFO_RX_BYTES |
-			STATION_INFO_TX_BYTES;
+			STATION_INFO_TX_BYTES |
+			STATION_INFO_TX_BITRATE;
 
 	sinfo->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx);
 	sinfo->rx_bytes = sta->rx_bytes;
 	sinfo->tx_bytes = sta->tx_bytes;
 
+	if (sta->local->hw.flags & IEEE80211_HW_SIGNAL_DBM) {
+		sinfo->filled |= STATION_INFO_SIGNAL;
+		sinfo->signal = sta->last_signal;
+	}
+
+	sinfo->txrate.flags = 0;
+	if (sta->last_tx_rate.flags & IEEE80211_TX_RC_MCS)
+		sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
+	if (sta->last_tx_rate.flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
+		sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
+	if (sta->last_tx_rate.flags & IEEE80211_TX_RC_SHORT_GI)
+		sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
+
+	if (!(sta->last_tx_rate.flags & IEEE80211_TX_RC_MCS)) {
+		struct ieee80211_supported_band *sband;
+		sband = sta->local->hw.wiphy->bands[sta->local->hw.conf.channel->band];
+		sinfo->txrate.legacy = sband->bitrates[sta->last_tx_rate.idx].bitrate;
+	}
+	else {
+		sinfo->txrate.mcs = sta->last_tx_rate.idx;
+	}
+
 	if (ieee80211_vif_is_mesh(&sdata->vif)) {
 #ifdef CONFIG_MAC80211_MESH
 		sinfo->filled |= STATION_INFO_LLID |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 9caee60..ced38a7 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -14,6 +14,7 @@
 #include <linux/nl80211.h>
 #include <linux/rtnetlink.h>
 #include <linux/netlink.h>
+#include <net/mac80211.h>
 #include <net/genetlink.h>
 #include <net/cfg80211.h>
 #include "core.h"
@@ -1084,7 +1085,7 @@ static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
 				u8 *mac_addr, struct station_info *sinfo)
 {
 	void *hdr;
-	struct nlattr *sinfoattr;
+	struct nlattr *sinfoattr, *txrate;
 
 	hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_STATION);
 	if (!hdr)
@@ -1114,7 +1115,28 @@ static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
 	if (sinfo->filled & STATION_INFO_PLINK_STATE)
 		NLA_PUT_U8(msg, NL80211_STA_INFO_PLINK_STATE,
 			    sinfo->plink_state);
+	if (sinfo->filled & STATION_INFO_SIGNAL)
+		NLA_PUT_U8(msg, NL80211_STA_INFO_SIGNAL,
+			   sinfo->signal);
+	if (sinfo->filled & STATION_INFO_TX_BITRATE) {
+		txrate = nla_nest_start(msg, NL80211_STA_INFO_TX_BITRATE);
+		if (!txrate)
+			goto nla_put_failure;
+
 
+		if (!(sinfo->txrate.flags & RATE_INFO_FLAGS_MCS))
+			NLA_PUT_U16(msg, NL80211_STA_INFO_RATE_LEGACY,
+				    sinfo->txrate.legacy);
+		else
+			NLA_PUT_U16(msg, NL80211_STA_INFO_RATE_MCS,
+				    sinfo->txrate.mcs);
+		if (sinfo->txrate.flags & RATE_INFO_FLAGS_40_MHZ_WIDTH)
+			NLA_PUT_FLAG(msg, NL80211_STA_INFO_RATE_40_MHZ_WIDTH);
+		if (sinfo->txrate.flags & RATE_INFO_FLAGS_SHORT_GI)
+			NLA_PUT_FLAG(msg, NL80211_STA_INFO_RATE_SHORT_GI);
+
+		nla_nest_end(msg, txrate);
+	}
 	nla_nest_end(msg, sinfoattr);
 
 	return genlmsg_end(msg, hdr);

[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 197 bytes --]

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

* Re: RFC Patch v2: Add signal strength to nl80211station info
  2008-12-07 17:32                                             ` Henning Rogge
@ 2008-12-07 17:39                                               ` Johannes Berg
  2008-12-07 18:17                                                 ` [PATCH 1/2] Add signal strength and bandwith " Henning Rogge
                                                                   ` (2 more replies)
  0 siblings, 3 replies; 66+ messages in thread
From: Johannes Berg @ 2008-12-07 17:39 UTC (permalink / raw)
  To: Henning Rogge
  Cc: Luis R. Rodriguez, Henning Rogge, Luis Rodriguez,
	Marcel Holtmann, linux-wireless, nbd

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

On Sun, 2008-12-07 at 18:32 +0100, Henning Rogge wrote:

> I think the suggestion is to remove the total/legacy bitrate for 802.11n 
> completely from the nl80211 station_info. Which I still think is not a good 
> idea. This way we force any  application displaying the bitrate to check for 
> several cases, know about the 802.11n table, ...
> I think it's funny that we have the "total bitrate" information available on 
> driver level but translate it into the mcs index with the help of tables... 
> and assume that userspace knows about the tables.

Alright, whatever, put it in, but please do the calculation in cfg80211
(nl80211.c). Should rename it to _TOTAL again then, though, I guess.

>  /**
> + * enum nl80211_sta_info_rate - station information about bitrate
> + *
> + * These attribute types are used with %NL80211_STA_INFO_TXRATE
> + * when getting information about the bitrate of a station.
> + *
> + * @__NL80211_STA_INFO_RATE_INVALID: attribute number 0 is reserved
> + * @NL80211_STA_INFO_RATE_LEGACY: bitrate for 802.11abg (u16, 100kbit/s)
> + * @NL80211_STA_INFO_RATE_MCS: mcs index for 802.11n (u8)
> + * @NL80211_STA_INFO_RATE_40_MHZ_WIDTH: 40 Mhz dualchannel bitrate
> + * @NL80211_STA_INFO_RATE_SHORT_GI: 400ns guard interval
> + */
> +enum nl80211_sta_info_rate {
> +	__NL80211_STA_INFO_RATE_INVALID,
> +	NL80211_STA_INFO_RATE_LEGACY,
> +	NL80211_STA_INFO_RATE_MCS,
> +	NL80211_STA_INFO_RATE_40_MHZ_WIDTH,
> +	NL80211_STA_INFO_RATE_SHORT_GI,
> +
> +	/* keep last */
> +	__NL80211_STA_INFO_RATE_AFTER_LAST,
> +	NL80211_STA_INFO_RATE_MAX = __NL80211_STA_INFO_RATE_AFTER_LAST - 1
> +};

Can you rename those too to NL80211_RATE_INFO_*? That way we can use
them for other things later.

But this looks good to me now.

johannes

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

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

* [PATCH 1/2] Add signal strength and bandwith to nl80211station info
  2008-12-07 17:39                                               ` Johannes Berg
@ 2008-12-07 18:17                                                 ` Henning Rogge
  2008-12-08 19:43                                                   ` Johannes Berg
  2008-12-07 18:19                                                 ` [PATCH 2/2] " Henning Rogge
  2008-12-07 18:20                                                 ` [PATCH 0/2] " Henning Rogge
  2 siblings, 1 reply; 66+ messages in thread
From: Henning Rogge @ 2008-12-07 18:17 UTC (permalink / raw)
  To: Johannes Berg
  Cc: Luis R. Rodriguez, Henning Rogge, Luis Rodriguez,
	Marcel Holtmann, linux-wireless, nbd


[-- Attachment #1.1: Type: text/plain, Size: 7395 bytes --]

This patch adds information about signal strength and unicast transmission 
bitrate to the nl80211 station info.

----------------------
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index 04d4516..56450b4 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -425,6 +425,30 @@ enum nl80211_sta_flags {
 };
 
 /**
+ * enum nl80211_rate_info - bitrate information
+ *
+ * These attribute types are used with %NL80211_STA_INFO_TXRATE
+ * when getting information about the bitrate of a station.
+ *
+ * @__NL80211_RATE_INFO_INVALID: attribute number 0 is reserved
+ * @NL80211_RATE_INFO_LEGACY: bitrate for 802.11abg (u16, 100kbit/s)
+ * @NL80211_RATE_INFO_MCS: mcs index for 802.11n (u8)
+ * @NL80211_RATE_INFO_40_MHZ_WIDTH: 40 Mhz dualchannel bitrate
+ * @NL80211_RATE_INFO_SHORT_GI: 400ns guard interval
+ */
+enum nl80211_rate_info {
+	__NL80211_RATE_INFO_INVALID,
+	NL80211_RATE_INFO_LEGACY,
+	NL80211_RATE_INFO_MCS,
+	NL80211_RATE_INFO_40_MHZ_WIDTH,
+	NL80211_RATE_INFO_SHORT_GI,
+
+	/* keep last */
+	__NL80211_RATE_INFO_AFTER_LAST,
+	NL80211_RATE_INFO_MAX = __NL80211_RATE_INFO_AFTER_LAST - 1
+};
+
+/**
  * enum nl80211_sta_info - station information
  *
  * These attribute types are used with %NL80211_ATTR_STA_INFO
@@ -436,6 +460,9 @@ enum nl80211_sta_flags {
  * @NL80211_STA_INFO_TX_BYTES: total transmitted bytes (u32, to this station)
  * @__NL80211_STA_INFO_AFTER_LAST: internal
  * @NL80211_STA_INFO_MAX: highest possible station info attribute
+ * @NL80211_STA_INFO_SIGNAL: signal strength of last received PPDU (u8, dBm)
+ * @NL80211_STA_INFO_TX_BITRATE: current unicast tx rate, nested attribute
+ * 	containing info as possible, see &enum nl80211_sta_info_txrate.
  */
 enum nl80211_sta_info {
 	__NL80211_STA_INFO_INVALID,
@@ -445,6 +472,8 @@ enum nl80211_sta_info {
 	NL80211_STA_INFO_LLID,
 	NL80211_STA_INFO_PLID,
 	NL80211_STA_INFO_PLINK_STATE,
+	NL80211_STA_INFO_SIGNAL,
+	NL80211_STA_INFO_TX_BITRATE,
 
 	/* keep last */
 	__NL80211_STA_INFO_AFTER_LAST,
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index a0c0bf1..d9ce51e 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -169,6 +169,9 @@ struct station_parameters {
  * @STATION_INFO_LLID: @llid filled
  * @STATION_INFO_PLID: @plid filled
  * @STATION_INFO_PLINK_STATE: @plink_state filled
+ * @STATION_INFO_SIGNAL: @signal filled
+ * @STATION_INFO_TX_BITRATE: @tx_bitrate fields are filled
+ *  (tx_bitrate, tx_bitrate_flags and tx_bitrate_mcs)
  */
 enum station_info_flags {
 	STATION_INFO_INACTIVE_TIME	= 1<<0,
@@ -177,6 +180,39 @@ enum station_info_flags {
 	STATION_INFO_LLID		= 1<<3,
 	STATION_INFO_PLID		= 1<<4,
 	STATION_INFO_PLINK_STATE	= 1<<5,
+	STATION_INFO_SIGNAL		= 1<<6,
+	STATION_INFO_TX_BITRATE		= 1<<7,
+};
+
+/**
+ * enum station_info_rate_flags - bitrate info flags
+ *
+ * Used by the driver to indicate the specific rate transmission
+ * type for 802.11n transmissions.
+ *
+ * @RATE_INFO_FLAGS_MCS: @tx_bitrate_mcs filled
+ * @RATE_INFO_FLAGS_40_MHZ_WIDTH: 40 Mhz width transmission
+ * @RATE_INFO_FLAGS_SHORT_GI: 400ns guard interval
+ */
+enum rate_info_flags {
+	RATE_INFO_FLAGS_MCS		= 1<<0,
+	RATE_INFO_FLAGS_40_MHZ_WIDTH	= 1<<1,
+	RATE_INFO_FLAGS_SHORT_GI	= 1<<2,
+};
+
+/**
+ * struct rate_info - bitrate information
+ *
+ * Information about a receiving or transmitting bitrate
+ *
+ * @flags: bitflag of flags from &enum rate_info_flags
+ * @mcs: mcs index if struct describes a 802.11n bitrate
+ * @legacy: bitrate in 100kbit/s for 802.11abg
+ */
+struct rate_info {
+	u8 flags;
+	u8 mcs;
+	u16 legacy;
 };
 
 /**
@@ -191,6 +227,8 @@ enum station_info_flags {
  * @llid: mesh local link id
  * @plid: mesh peer link id
  * @plink_state: mesh peer link state
+ * @signal: signal strength of last received package in dBm
+ * @txrate: current unicast bitrate to this station
  */
 struct station_info {
 	u32 filled;
@@ -200,6 +238,8 @@ struct station_info {
 	u16 llid;
 	u16 plid;
 	u8 plink_state;
+	u8 signal;
+	struct rate_info txrate;
 };
 
 /**
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 7a7a6c1..e6c2b7a 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -310,12 +310,35 @@ static void sta_set_sinfo(struct sta_info *sta, struct 
station_info *sinfo)
 
 	sinfo->filled = STATION_INFO_INACTIVE_TIME |
 			STATION_INFO_RX_BYTES |
-			STATION_INFO_TX_BYTES;
+			STATION_INFO_TX_BYTES |
+			STATION_INFO_TX_BITRATE;
 
 	sinfo->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx);
 	sinfo->rx_bytes = sta->rx_bytes;
 	sinfo->tx_bytes = sta->tx_bytes;
 
+	if (sta->local->hw.flags & IEEE80211_HW_SIGNAL_DBM) {
+		sinfo->filled |= STATION_INFO_SIGNAL;
+		sinfo->signal = sta->last_signal;
+	}
+
+	sinfo->txrate.flags = 0;
+	if (sta->last_tx_rate.flags & IEEE80211_TX_RC_MCS)
+		sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
+	if (sta->last_tx_rate.flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
+		sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
+	if (sta->last_tx_rate.flags & IEEE80211_TX_RC_SHORT_GI)
+		sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
+
+	if (!(sta->last_tx_rate.flags & IEEE80211_TX_RC_MCS)) {
+		struct ieee80211_supported_band *sband;
+		sband = sta->local->hw.wiphy->bands[sta->local->hw.conf.channel->band];
+		sinfo->txrate.legacy = sband->bitrates[sta->last_tx_rate.idx].bitrate;
+	}
+	else {
+		sinfo->txrate.mcs = sta->last_tx_rate.idx;
+	}
+
 	if (ieee80211_vif_is_mesh(&sdata->vif)) {
 #ifdef CONFIG_MAC80211_MESH
 		sinfo->filled |= STATION_INFO_LLID |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 9caee60..c9268b2 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -14,6 +14,7 @@
 #include <linux/nl80211.h>
 #include <linux/rtnetlink.h>
 #include <linux/netlink.h>
+#include <net/mac80211.h>
 #include <net/genetlink.h>
 #include <net/cfg80211.h>
 #include "core.h"
@@ -1084,7 +1085,7 @@ static int nl80211_send_station(struct sk_buff *msg, u32 
pid, u32 seq,
 				u8 *mac_addr, struct station_info *sinfo)
 {
 	void *hdr;
-	struct nlattr *sinfoattr;
+	struct nlattr *sinfoattr, *txrate;
 
 	hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_STATION);
 	if (!hdr)
@@ -1114,7 +1115,28 @@ static int nl80211_send_station(struct sk_buff *msg, 
u32 pid, u32 seq,
 	if (sinfo->filled & STATION_INFO_PLINK_STATE)
 		NLA_PUT_U8(msg, NL80211_STA_INFO_PLINK_STATE,
 			    sinfo->plink_state);
+	if (sinfo->filled & STATION_INFO_SIGNAL)
+		NLA_PUT_U8(msg, NL80211_STA_INFO_SIGNAL,
+			   sinfo->signal);
+	if (sinfo->filled & STATION_INFO_TX_BITRATE) {
+		txrate = nla_nest_start(msg, NL80211_STA_INFO_TX_BITRATE);
+		if (!txrate)
+			goto nla_put_failure;
+
 
+		if (!(sinfo->txrate.flags & RATE_INFO_FLAGS_MCS))
+			NLA_PUT_U16(msg, NL80211_RATE_INFO_LEGACY,
+				    sinfo->txrate.legacy);
+		else
+			NLA_PUT_U8(msg, NL80211_RATE_INFO_MCS,
+				    sinfo->txrate.mcs);
+		if (sinfo->txrate.flags & RATE_INFO_FLAGS_40_MHZ_WIDTH)
+			NLA_PUT_FLAG(msg, NL80211_RATE_INFO_40_MHZ_WIDTH);
+		if (sinfo->txrate.flags & RATE_INFO_FLAGS_SHORT_GI)
+			NLA_PUT_FLAG(msg, NL80211_RATE_INFO_SHORT_GI);
+
+		nla_nest_end(msg, txrate);
+	}
 	nla_nest_end(msg, sinfoattr);
 
 	return genlmsg_end(msg, hdr);


[-- Attachment #1.2: nl80211ext_v8_1.patch --]
[-- Type: text/x-patch, Size: 7246 bytes --]

diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index 04d4516..56450b4 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -425,6 +425,30 @@ enum nl80211_sta_flags {
 };
 
 /**
+ * enum nl80211_rate_info - bitrate information
+ *
+ * These attribute types are used with %NL80211_STA_INFO_TXRATE
+ * when getting information about the bitrate of a station.
+ *
+ * @__NL80211_RATE_INFO_INVALID: attribute number 0 is reserved
+ * @NL80211_RATE_INFO_LEGACY: bitrate for 802.11abg (u16, 100kbit/s)
+ * @NL80211_RATE_INFO_MCS: mcs index for 802.11n (u8)
+ * @NL80211_RATE_INFO_40_MHZ_WIDTH: 40 Mhz dualchannel bitrate
+ * @NL80211_RATE_INFO_SHORT_GI: 400ns guard interval
+ */
+enum nl80211_rate_info {
+	__NL80211_RATE_INFO_INVALID,
+	NL80211_RATE_INFO_LEGACY,
+	NL80211_RATE_INFO_MCS,
+	NL80211_RATE_INFO_40_MHZ_WIDTH,
+	NL80211_RATE_INFO_SHORT_GI,
+
+	/* keep last */
+	__NL80211_RATE_INFO_AFTER_LAST,
+	NL80211_RATE_INFO_MAX = __NL80211_RATE_INFO_AFTER_LAST - 1
+};
+
+/**
  * enum nl80211_sta_info - station information
  *
  * These attribute types are used with %NL80211_ATTR_STA_INFO
@@ -436,6 +460,9 @@ enum nl80211_sta_flags {
  * @NL80211_STA_INFO_TX_BYTES: total transmitted bytes (u32, to this station)
  * @__NL80211_STA_INFO_AFTER_LAST: internal
  * @NL80211_STA_INFO_MAX: highest possible station info attribute
+ * @NL80211_STA_INFO_SIGNAL: signal strength of last received PPDU (u8, dBm)
+ * @NL80211_STA_INFO_TX_BITRATE: current unicast tx rate, nested attribute
+ * 	containing info as possible, see &enum nl80211_sta_info_txrate.
  */
 enum nl80211_sta_info {
 	__NL80211_STA_INFO_INVALID,
@@ -445,6 +472,8 @@ enum nl80211_sta_info {
 	NL80211_STA_INFO_LLID,
 	NL80211_STA_INFO_PLID,
 	NL80211_STA_INFO_PLINK_STATE,
+	NL80211_STA_INFO_SIGNAL,
+	NL80211_STA_INFO_TX_BITRATE,
 
 	/* keep last */
 	__NL80211_STA_INFO_AFTER_LAST,
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index a0c0bf1..d9ce51e 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -169,6 +169,9 @@ struct station_parameters {
  * @STATION_INFO_LLID: @llid filled
  * @STATION_INFO_PLID: @plid filled
  * @STATION_INFO_PLINK_STATE: @plink_state filled
+ * @STATION_INFO_SIGNAL: @signal filled
+ * @STATION_INFO_TX_BITRATE: @tx_bitrate fields are filled
+ *  (tx_bitrate, tx_bitrate_flags and tx_bitrate_mcs)
  */
 enum station_info_flags {
 	STATION_INFO_INACTIVE_TIME	= 1<<0,
@@ -177,6 +180,39 @@ enum station_info_flags {
 	STATION_INFO_LLID		= 1<<3,
 	STATION_INFO_PLID		= 1<<4,
 	STATION_INFO_PLINK_STATE	= 1<<5,
+	STATION_INFO_SIGNAL		= 1<<6,
+	STATION_INFO_TX_BITRATE		= 1<<7,
+};
+
+/**
+ * enum station_info_rate_flags - bitrate info flags
+ *
+ * Used by the driver to indicate the specific rate transmission
+ * type for 802.11n transmissions.
+ *
+ * @RATE_INFO_FLAGS_MCS: @tx_bitrate_mcs filled
+ * @RATE_INFO_FLAGS_40_MHZ_WIDTH: 40 Mhz width transmission
+ * @RATE_INFO_FLAGS_SHORT_GI: 400ns guard interval
+ */
+enum rate_info_flags {
+	RATE_INFO_FLAGS_MCS		= 1<<0,
+	RATE_INFO_FLAGS_40_MHZ_WIDTH	= 1<<1,
+	RATE_INFO_FLAGS_SHORT_GI	= 1<<2,
+};
+
+/**
+ * struct rate_info - bitrate information
+ *
+ * Information about a receiving or transmitting bitrate
+ *
+ * @flags: bitflag of flags from &enum rate_info_flags
+ * @mcs: mcs index if struct describes a 802.11n bitrate
+ * @legacy: bitrate in 100kbit/s for 802.11abg
+ */
+struct rate_info {
+	u8 flags;
+	u8 mcs;
+	u16 legacy;
 };
 
 /**
@@ -191,6 +227,8 @@ enum station_info_flags {
  * @llid: mesh local link id
  * @plid: mesh peer link id
  * @plink_state: mesh peer link state
+ * @signal: signal strength of last received package in dBm
+ * @txrate: current unicast bitrate to this station
  */
 struct station_info {
 	u32 filled;
@@ -200,6 +238,8 @@ struct station_info {
 	u16 llid;
 	u16 plid;
 	u8 plink_state;
+	u8 signal;
+	struct rate_info txrate;
 };
 
 /**
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 7a7a6c1..e6c2b7a 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -310,12 +310,35 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
 
 	sinfo->filled = STATION_INFO_INACTIVE_TIME |
 			STATION_INFO_RX_BYTES |
-			STATION_INFO_TX_BYTES;
+			STATION_INFO_TX_BYTES |
+			STATION_INFO_TX_BITRATE;
 
 	sinfo->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx);
 	sinfo->rx_bytes = sta->rx_bytes;
 	sinfo->tx_bytes = sta->tx_bytes;
 
+	if (sta->local->hw.flags & IEEE80211_HW_SIGNAL_DBM) {
+		sinfo->filled |= STATION_INFO_SIGNAL;
+		sinfo->signal = sta->last_signal;
+	}
+
+	sinfo->txrate.flags = 0;
+	if (sta->last_tx_rate.flags & IEEE80211_TX_RC_MCS)
+		sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
+	if (sta->last_tx_rate.flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
+		sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
+	if (sta->last_tx_rate.flags & IEEE80211_TX_RC_SHORT_GI)
+		sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
+
+	if (!(sta->last_tx_rate.flags & IEEE80211_TX_RC_MCS)) {
+		struct ieee80211_supported_band *sband;
+		sband = sta->local->hw.wiphy->bands[sta->local->hw.conf.channel->band];
+		sinfo->txrate.legacy = sband->bitrates[sta->last_tx_rate.idx].bitrate;
+	}
+	else {
+		sinfo->txrate.mcs = sta->last_tx_rate.idx;
+	}
+
 	if (ieee80211_vif_is_mesh(&sdata->vif)) {
 #ifdef CONFIG_MAC80211_MESH
 		sinfo->filled |= STATION_INFO_LLID |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 9caee60..c9268b2 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -14,6 +14,7 @@
 #include <linux/nl80211.h>
 #include <linux/rtnetlink.h>
 #include <linux/netlink.h>
+#include <net/mac80211.h>
 #include <net/genetlink.h>
 #include <net/cfg80211.h>
 #include "core.h"
@@ -1084,7 +1085,7 @@ static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
 				u8 *mac_addr, struct station_info *sinfo)
 {
 	void *hdr;
-	struct nlattr *sinfoattr;
+	struct nlattr *sinfoattr, *txrate;
 
 	hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_STATION);
 	if (!hdr)
@@ -1114,7 +1115,28 @@ static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
 	if (sinfo->filled & STATION_INFO_PLINK_STATE)
 		NLA_PUT_U8(msg, NL80211_STA_INFO_PLINK_STATE,
 			    sinfo->plink_state);
+	if (sinfo->filled & STATION_INFO_SIGNAL)
+		NLA_PUT_U8(msg, NL80211_STA_INFO_SIGNAL,
+			   sinfo->signal);
+	if (sinfo->filled & STATION_INFO_TX_BITRATE) {
+		txrate = nla_nest_start(msg, NL80211_STA_INFO_TX_BITRATE);
+		if (!txrate)
+			goto nla_put_failure;
+
 
+		if (!(sinfo->txrate.flags & RATE_INFO_FLAGS_MCS))
+			NLA_PUT_U16(msg, NL80211_RATE_INFO_LEGACY,
+				    sinfo->txrate.legacy);
+		else
+			NLA_PUT_U8(msg, NL80211_RATE_INFO_MCS,
+				    sinfo->txrate.mcs);
+		if (sinfo->txrate.flags & RATE_INFO_FLAGS_40_MHZ_WIDTH)
+			NLA_PUT_FLAG(msg, NL80211_RATE_INFO_40_MHZ_WIDTH);
+		if (sinfo->txrate.flags & RATE_INFO_FLAGS_SHORT_GI)
+			NLA_PUT_FLAG(msg, NL80211_RATE_INFO_SHORT_GI);
+
+		nla_nest_end(msg, txrate);
+	}
 	nla_nest_end(msg, sinfoattr);
 
 	return genlmsg_end(msg, hdr);

[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 197 bytes --]

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

* [PATCH 2/2] Add signal strength and bandwith to nl80211station info
  2008-12-07 17:39                                               ` Johannes Berg
  2008-12-07 18:17                                                 ` [PATCH 1/2] Add signal strength and bandwith " Henning Rogge
@ 2008-12-07 18:19                                                 ` Henning Rogge
  2008-12-07 18:20                                                 ` [PATCH 0/2] " Henning Rogge
  2 siblings, 0 replies; 66+ messages in thread
From: Henning Rogge @ 2008-12-07 18:19 UTC (permalink / raw)
  To: Johannes Berg
  Cc: Luis R. Rodriguez, Henning Rogge, Luis Rodriguez,
	Marcel Holtmann, linux-wireless, nbd


[-- Attachment #1.1: Type: text/plain, Size: 2846 bytes --]

This patch adds the total transmission bitrate for adhoc station even for 
802.11n transmissions. It must be applied after the first patch of this 
series.

-------------------------
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index 56450b4..b5abe36 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -431,14 +431,14 @@ enum nl80211_sta_flags {
  * when getting information about the bitrate of a station.
  *
  * @__NL80211_RATE_INFO_INVALID: attribute number 0 is reserved
- * @NL80211_RATE_INFO_LEGACY: bitrate for 802.11abg (u16, 100kbit/s)
+ * @NL80211_RATE_INFO_TOTAL: total bitrate (u16, 100kbit/s)
  * @NL80211_RATE_INFO_MCS: mcs index for 802.11n (u8)
  * @NL80211_RATE_INFO_40_MHZ_WIDTH: 40 Mhz dualchannel bitrate
  * @NL80211_RATE_INFO_SHORT_GI: 400ns guard interval
  */
 enum nl80211_rate_info {
 	__NL80211_RATE_INFO_INVALID,
-	NL80211_RATE_INFO_LEGACY,
+	NL80211_RATE_INFO_TOTAL,
 	NL80211_RATE_INFO_MCS,
 	NL80211_RATE_INFO_40_MHZ_WIDTH,
 	NL80211_RATE_INFO_SHORT_GI,
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index c9268b2..8689744 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -1080,6 +1080,35 @@ static int parse_station_flags(struct nlattr *nla, u32 
*staflags)
 	return 0;
 }
 
+static u16 nl80211_calculate_bitrate(struct rate_info *rate)
+{
+	int modulation, streams, bitrate;
+
+	if (!(rate->flags & RATE_INFO_FLAGS_MCS))
+		return rate->legacy;
+
+	modulation = rate->mcs & 7;
+	streams = rate->mcs >> 3;
+
+	bitrate = (rate->flags & RATE_INFO_FLAGS_40_MHZ_WIDTH) ?
+			13500000 : 6500000;
+
+	if (modulation < 4)
+		bitrate *= (modulation + 1);
+	else if (modulation == 4)
+		bitrate *= (modulation + 2);
+	else
+		bitrate *= (modulation + 3);
+
+	bitrate *= streams;
+
+	if (rate->flags & RATE_INFO_FLAGS_SHORT_GI)
+		bitrate = (bitrate * 10) / 9;
+
+	/* do NOT round down here */
+	return (bitrate + 50000) / 100000;
+}
+
 static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
 				int flags, struct net_device *dev,
 				u8 *mac_addr, struct station_info *sinfo)
@@ -1123,13 +1152,12 @@ static int nl80211_send_station(struct sk_buff *msg, 
u32 pid, u32 seq,
 		if (!txrate)
 			goto nla_put_failure;
 
-
-		if (!(sinfo->txrate.flags & RATE_INFO_FLAGS_MCS))
-			NLA_PUT_U16(msg, NL80211_RATE_INFO_LEGACY,
-				    sinfo->txrate.legacy);
-		else
+		NLA_PUT_U16(msg, NL80211_RATE_INFO_TOTAL,
+				nl80211_calculate_bitrate(&sinfo->txrate));
+		if (sinfo->txrate.flags & RATE_INFO_FLAGS_MCS)
 			NLA_PUT_U8(msg, NL80211_RATE_INFO_MCS,
 				    sinfo->txrate.mcs);
+
 		if (sinfo->txrate.flags & RATE_INFO_FLAGS_40_MHZ_WIDTH)
 			NLA_PUT_FLAG(msg, NL80211_RATE_INFO_40_MHZ_WIDTH);
 		if (sinfo->txrate.flags & RATE_INFO_FLAGS_SHORT_GI)


[-- Attachment #1.2: nl80211ext_v8_2.patch --]
[-- Type: text/x-patch, Size: 2652 bytes --]

diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index 56450b4..b5abe36 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -431,14 +431,14 @@ enum nl80211_sta_flags {
  * when getting information about the bitrate of a station.
  *
  * @__NL80211_RATE_INFO_INVALID: attribute number 0 is reserved
- * @NL80211_RATE_INFO_LEGACY: bitrate for 802.11abg (u16, 100kbit/s)
+ * @NL80211_RATE_INFO_TOTAL: total bitrate (u16, 100kbit/s)
  * @NL80211_RATE_INFO_MCS: mcs index for 802.11n (u8)
  * @NL80211_RATE_INFO_40_MHZ_WIDTH: 40 Mhz dualchannel bitrate
  * @NL80211_RATE_INFO_SHORT_GI: 400ns guard interval
  */
 enum nl80211_rate_info {
 	__NL80211_RATE_INFO_INVALID,
-	NL80211_RATE_INFO_LEGACY,
+	NL80211_RATE_INFO_TOTAL,
 	NL80211_RATE_INFO_MCS,
 	NL80211_RATE_INFO_40_MHZ_WIDTH,
 	NL80211_RATE_INFO_SHORT_GI,
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index c9268b2..8689744 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -1080,6 +1080,35 @@ static int parse_station_flags(struct nlattr *nla, u32 *staflags)
 	return 0;
 }
 
+static u16 nl80211_calculate_bitrate(struct rate_info *rate)
+{
+	int modulation, streams, bitrate;
+
+	if (!(rate->flags & RATE_INFO_FLAGS_MCS))
+		return rate->legacy;
+
+	modulation = rate->mcs & 7;
+	streams = rate->mcs >> 3;
+
+	bitrate = (rate->flags & RATE_INFO_FLAGS_40_MHZ_WIDTH) ?
+			13500000 : 6500000;
+
+	if (modulation < 4)
+		bitrate *= (modulation + 1);
+	else if (modulation == 4)
+		bitrate *= (modulation + 2);
+	else
+		bitrate *= (modulation + 3);
+
+	bitrate *= streams;
+
+	if (rate->flags & RATE_INFO_FLAGS_SHORT_GI)
+		bitrate = (bitrate * 10) / 9;
+
+	/* do NOT round down here */
+	return (bitrate + 50000) / 100000;
+}
+
 static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
 				int flags, struct net_device *dev,
 				u8 *mac_addr, struct station_info *sinfo)
@@ -1123,13 +1152,12 @@ static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
 		if (!txrate)
 			goto nla_put_failure;
 
-
-		if (!(sinfo->txrate.flags & RATE_INFO_FLAGS_MCS))
-			NLA_PUT_U16(msg, NL80211_RATE_INFO_LEGACY,
-				    sinfo->txrate.legacy);
-		else
+		NLA_PUT_U16(msg, NL80211_RATE_INFO_TOTAL,
+				nl80211_calculate_bitrate(&sinfo->txrate));
+		if (sinfo->txrate.flags & RATE_INFO_FLAGS_MCS)
 			NLA_PUT_U8(msg, NL80211_RATE_INFO_MCS,
 				    sinfo->txrate.mcs);
+
 		if (sinfo->txrate.flags & RATE_INFO_FLAGS_40_MHZ_WIDTH)
 			NLA_PUT_FLAG(msg, NL80211_RATE_INFO_40_MHZ_WIDTH);
 		if (sinfo->txrate.flags & RATE_INFO_FLAGS_SHORT_GI)

[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 197 bytes --]

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

* [PATCH 0/2] Add signal strength and bandwith to nl80211station info
  2008-12-07 17:39                                               ` Johannes Berg
  2008-12-07 18:17                                                 ` [PATCH 1/2] Add signal strength and bandwith " Henning Rogge
  2008-12-07 18:19                                                 ` [PATCH 2/2] " Henning Rogge
@ 2008-12-07 18:20                                                 ` Henning Rogge
  2 siblings, 0 replies; 66+ messages in thread
From: Henning Rogge @ 2008-12-07 18:20 UTC (permalink / raw)
  To: Johannes Berg
  Cc: Luis R. Rodriguez, Henning Rogge, Luis Rodriguez,
	Marcel Holtmann, linux-wireless, nbd

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

On Sunday 07 December 2008 18:39:38 Johannes Berg wrote:
> Can you rename those too to NL80211_RATE_INFO_*? That way we can use
> them for other things later.
>
> But this looks good to me now.

I have splitted the patch into two parts so a better review is possible 
without deciding if we put the total bandwith into nl80211 or not.

Changes since v1:
- removed noise and quality from station info in NL80211
- added bandwith to station info in NL80211
- changed name of patch file to nl80211ext_v2.patch
  
Changes since v2:
- added kernel comment lines for new fields/enums
- changed name of "bandwith" field to tx_bitrate

Changes since v3:
- added rx_bitrate to station info and sta_info
- remember bitrate of last received unicast packet to this station
- decode 802.11n MCS index for nl80211
  (maybe this should be ported to WEXT too ?)

Changes since v4:
- added tx_bitrate_flags adn tx_bitrate_mcs field to station info
- added flags for 40Mhz and small guard interval to NL80211 station info
- added mcs field to NL80211 station info

Changes since v5:
- remove rx_bitrate from patch until we get a sane way to learn the details of 
 
received 802.11n packages
-replace 802.11n bitrate arrays with calculation based on basic rates
- pushed txrate nl80211 stationinfo into nested attribute
- created station_info_rate_flags enum to save bitrate flags in station_info
- cleanup of kerneldoc

Changes since v6:
- removed mcs index to bitrate conversion
- push station info bitrate into substructure
- renamed "total" bitrate into "legacy"
- some code cleanup

Changes since v7:
- corrected a small type in nl80211 mcs representation
- splitted patch into two parts

TODO:
- tests with real 802.11n hardware
- more tests with 802.11abg hardware

Henning


[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 197 bytes --]

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

* Re: [PATCH 1/2] Add signal strength and bandwith to nl80211station info
  2008-12-07 18:17                                                 ` [PATCH 1/2] Add signal strength and bandwith " Henning Rogge
@ 2008-12-08 19:43                                                   ` Johannes Berg
  2008-12-09 19:50                                                     ` Henning Rogge
                                                                       ` (2 more replies)
  0 siblings, 3 replies; 66+ messages in thread
From: Johannes Berg @ 2008-12-08 19:43 UTC (permalink / raw)
  To: Henning Rogge
  Cc: Luis R. Rodriguez, Henning Rogge, Luis Rodriguez,
	Marcel Holtmann, linux-wireless, nbd

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

On Sun, 2008-12-07 at 19:17 +0100, Henning Rogge wrote:

> + * @NL80211_RATE_INFO_LEGACY: bitrate for 802.11abg (u16, 100kbit/s)

Your other patch named this _TOTAL, can you rename it to _BITRATE
instead?

> +	if (!(sta->last_tx_rate.flags & IEEE80211_TX_RC_MCS)) {
> +		struct ieee80211_supported_band *sband;
> +		sband = sta->local->hw.wiphy->bands[sta->local->hw.conf.channel->band];
> +		sinfo->txrate.legacy = sband->bitrates[sta->last_tx_rate.idx].bitrate;
> +	}
> +	else {
> +		sinfo->txrate.mcs = sta->last_tx_rate.idx;
> +	}

Put the else on the same line as the closing brace, please.

> --- a/net/wireless/nl80211.c
> +++ b/net/wireless/nl80211.c
> @@ -14,6 +14,7 @@
>  #include <linux/nl80211.h>
>  #include <linux/rtnetlink.h>
>  #include <linux/netlink.h>
> +#include <net/mac80211.h>
>  #include <net/genetlink.h>
>  #include <net/cfg80211.h>
>  #include "core.h"

That has to go.

And on your second patch:

> +static u16 nl80211_calculate_bitrate(struct rate_info *rate)
> +{
> +       int modulation, streams, bitrate;
> +
> +       if (!(rate->flags & RATE_INFO_FLAGS_MCS))
> +               return rate->legacy;
> +
> +       modulation = rate->mcs & 7;
> +       streams = rate->mcs >> 3;

I don't think this gives correct results for MCS rates 32 through 76,
does it? It should at least not calculate anything then. If we did it in
userspace then programs could also actually calculate the correct rate
as a float, rather than this approximation. Not that it'll matter, I
guess. Doesn't anybody know how to do the actual calculation?

johannes

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

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

* Re: [PATCH 1/2] Add signal strength and bandwith to nl80211station info
  2008-12-08 19:43                                                   ` Johannes Berg
@ 2008-12-09 19:50                                                     ` Henning Rogge
  2008-12-09 21:16                                                       ` Johannes Berg
  2008-12-09 19:54                                                     ` [Patch 1/2 v2] " Henning Rogge
  2008-12-09 19:58                                                     ` [Patch 2/2 " Henning Rogge
  2 siblings, 1 reply; 66+ messages in thread
From: Henning Rogge @ 2008-12-09 19:50 UTC (permalink / raw)
  To: Johannes Berg
  Cc: Luis R. Rodriguez, Henning Rogge, Luis Rodriguez,
	Marcel Holtmann, linux-wireless, nbd


[-- Attachment #1.1: Type: text/plain, Size: 961 bytes --]

On Monday 08 December 2008 20:43:35 you wrote:
> And on your second patch:
> > +static u16 nl80211_calculate_bitrate(struct rate_info *rate)
> > +{
> > +       int modulation, streams, bitrate;
> > +
> > +       if (!(rate->flags & RATE_INFO_FLAGS_MCS))
> > +               return rate->legacy;
> > +
> > +       modulation = rate->mcs & 7;
> > +       streams = rate->mcs >> 3;

> I don't think this gives correct results for MCS rates 32 through 76,
> does it? It should at least not calculate anything then. If we did it in
> userspace then programs could also actually calculate the correct rate
> as a float, rather than this approximation. Not that it'll matter, I
> guess. Doesn't anybody know how to do the actual calculation?
It had a small type (corrected in the new patches), but I think the values are 
good. I have attached a test programm to this mail that outputs the bandwith 
values calculated by the function.

Henning


[-- Attachment #1.2: calctest.c --]
[-- Type: text/x-csrc, Size: 1717 bytes --]

#include <stdio.h>

#define RATE_INFO_FLAGS_MCS 1
#define RATE_INFO_FLAGS_40_MHZ_WIDTH 2
#define RATE_INFO_FLAGS_SHORT_GI 4

struct rate_info {
	int flags, mcs, legacy;
};

int nl80211_calculate_bitrate(struct rate_info *rate)
{
	int modulation, streams, bitrate;

	if (!(rate->flags & RATE_INFO_FLAGS_MCS))
		return rate->legacy;

	modulation = rate->mcs & 7;
	streams = (rate->mcs >> 3) + 1;

	bitrate = (rate->flags & RATE_INFO_FLAGS_40_MHZ_WIDTH) ?
			13500000 : 6500000;

	if (modulation < 4)
		bitrate *= (modulation + 1);
	else if (modulation == 4)
		bitrate *= (modulation + 2);
	else
		bitrate *= (modulation + 3);

	bitrate *= streams;

	if (rate->flags & RATE_INFO_FLAGS_SHORT_GI)
		bitrate = (bitrate / 9) * 10;

	/* do NOT round down here */
	return (bitrate + 50000) / 100000;
}

int main(int argc, char **argv) {
	struct rate_info ri;
	int mcs;

	printf("20 Mhz wide channels\n");
	for (mcs = 0; mcs < 72; mcs++) {
		int r1, r2;
		
		ri.mcs = mcs;
		
		ri.flags = RATE_INFO_FLAGS_MCS;
		r1 = nl80211_calculate_bitrate(&ri);

		ri.flags = RATE_INFO_FLAGS_MCS | RATE_INFO_FLAGS_SHORT_GI;
		r2 = nl80211_calculate_bitrate(&ri);

		printf("mcs %d:    long gi %4d / short gi %4d\n", mcs, r1, r2);
	}
	
	printf("\n");
	printf("40 Mhz wide channels\n");

	for (mcs = 0; mcs < 72; mcs++) {
		int r1, r2;

		ri.mcs = mcs;
		
		ri.flags = RATE_INFO_FLAGS_MCS | RATE_INFO_FLAGS_40_MHZ_WIDTH;
		r1 = nl80211_calculate_bitrate(&ri);

		ri.flags = RATE_INFO_FLAGS_MCS | RATE_INFO_FLAGS_SHORT_GI | RATE_INFO_FLAGS_40_MHZ_WIDTH;
		r2 = nl80211_calculate_bitrate(&ri);

		printf("mcs %d:    long gi %4d / short gi %4d\n", mcs, r1, r2);
	}
	
}

[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 197 bytes --]

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

* [Patch 1/2 v2] Add signal strength and bandwith to nl80211station info
  2008-12-08 19:43                                                   ` Johannes Berg
  2008-12-09 19:50                                                     ` Henning Rogge
@ 2008-12-09 19:54                                                     ` Henning Rogge
  2008-12-09 19:58                                                     ` [Patch 2/2 " Henning Rogge
  2 siblings, 0 replies; 66+ messages in thread
From: Henning Rogge @ 2008-12-09 19:54 UTC (permalink / raw)
  To: Johannes Berg
  Cc: Luis R. Rodriguez, Henning Rogge, Luis Rodriguez,
	Marcel Holtmann, linux-wireless, nbd


[-- Attachment #1.1: Type: text/plain, Size: 7198 bytes --]

This patch adds information about signal strength and unicast transmission 
bitrate to the nl80211 station info.

------------------------------------
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index 04d4516..56450b4 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -425,6 +425,30 @@ enum nl80211_sta_flags {
 };
 
 /**
+ * enum nl80211_rate_info - bitrate information
+ *
+ * These attribute types are used with %NL80211_STA_INFO_TXRATE
+ * when getting information about the bitrate of a station.
+ *
+ * @__NL80211_RATE_INFO_INVALID: attribute number 0 is reserved
+ * @NL80211_RATE_INFO_LEGACY: bitrate for 802.11abg (u16, 100kbit/s)
+ * @NL80211_RATE_INFO_MCS: mcs index for 802.11n (u8)
+ * @NL80211_RATE_INFO_40_MHZ_WIDTH: 40 Mhz dualchannel bitrate
+ * @NL80211_RATE_INFO_SHORT_GI: 400ns guard interval
+ */
+enum nl80211_rate_info {
+	__NL80211_RATE_INFO_INVALID,
+	NL80211_RATE_INFO_LEGACY,
+	NL80211_RATE_INFO_MCS,
+	NL80211_RATE_INFO_40_MHZ_WIDTH,
+	NL80211_RATE_INFO_SHORT_GI,
+
+	/* keep last */
+	__NL80211_RATE_INFO_AFTER_LAST,
+	NL80211_RATE_INFO_MAX = __NL80211_RATE_INFO_AFTER_LAST - 1
+};
+
+/**
  * enum nl80211_sta_info - station information
  *
  * These attribute types are used with %NL80211_ATTR_STA_INFO
@@ -436,6 +460,9 @@ enum nl80211_sta_flags {
  * @NL80211_STA_INFO_TX_BYTES: total transmitted bytes (u32, to this station)
  * @__NL80211_STA_INFO_AFTER_LAST: internal
  * @NL80211_STA_INFO_MAX: highest possible station info attribute
+ * @NL80211_STA_INFO_SIGNAL: signal strength of last received PPDU (u8, dBm)
+ * @NL80211_STA_INFO_TX_BITRATE: current unicast tx rate, nested attribute
+ * 	containing info as possible, see &enum nl80211_sta_info_txrate.
  */
 enum nl80211_sta_info {
 	__NL80211_STA_INFO_INVALID,
@@ -445,6 +472,8 @@ enum nl80211_sta_info {
 	NL80211_STA_INFO_LLID,
 	NL80211_STA_INFO_PLID,
 	NL80211_STA_INFO_PLINK_STATE,
+	NL80211_STA_INFO_SIGNAL,
+	NL80211_STA_INFO_TX_BITRATE,
 
 	/* keep last */
 	__NL80211_STA_INFO_AFTER_LAST,
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index a0c0bf1..d9ce51e 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -169,6 +169,9 @@ struct station_parameters {
  * @STATION_INFO_LLID: @llid filled
  * @STATION_INFO_PLID: @plid filled
  * @STATION_INFO_PLINK_STATE: @plink_state filled
+ * @STATION_INFO_SIGNAL: @signal filled
+ * @STATION_INFO_TX_BITRATE: @tx_bitrate fields are filled
+ *  (tx_bitrate, tx_bitrate_flags and tx_bitrate_mcs)
  */
 enum station_info_flags {
 	STATION_INFO_INACTIVE_TIME	= 1<<0,
@@ -177,6 +180,39 @@ enum station_info_flags {
 	STATION_INFO_LLID		= 1<<3,
 	STATION_INFO_PLID		= 1<<4,
 	STATION_INFO_PLINK_STATE	= 1<<5,
+	STATION_INFO_SIGNAL		= 1<<6,
+	STATION_INFO_TX_BITRATE		= 1<<7,
+};
+
+/**
+ * enum station_info_rate_flags - bitrate info flags
+ *
+ * Used by the driver to indicate the specific rate transmission
+ * type for 802.11n transmissions.
+ *
+ * @RATE_INFO_FLAGS_MCS: @tx_bitrate_mcs filled
+ * @RATE_INFO_FLAGS_40_MHZ_WIDTH: 40 Mhz width transmission
+ * @RATE_INFO_FLAGS_SHORT_GI: 400ns guard interval
+ */
+enum rate_info_flags {
+	RATE_INFO_FLAGS_MCS		= 1<<0,
+	RATE_INFO_FLAGS_40_MHZ_WIDTH	= 1<<1,
+	RATE_INFO_FLAGS_SHORT_GI	= 1<<2,
+};
+
+/**
+ * struct rate_info - bitrate information
+ *
+ * Information about a receiving or transmitting bitrate
+ *
+ * @flags: bitflag of flags from &enum rate_info_flags
+ * @mcs: mcs index if struct describes a 802.11n bitrate
+ * @legacy: bitrate in 100kbit/s for 802.11abg
+ */
+struct rate_info {
+	u8 flags;
+	u8 mcs;
+	u16 legacy;
 };
 
 /**
@@ -191,6 +227,8 @@ enum station_info_flags {
  * @llid: mesh local link id
  * @plid: mesh peer link id
  * @plink_state: mesh peer link state
+ * @signal: signal strength of last received package in dBm
+ * @txrate: current unicast bitrate to this station
  */
 struct station_info {
 	u32 filled;
@@ -200,6 +238,8 @@ struct station_info {
 	u16 llid;
 	u16 plid;
 	u8 plink_state;
+	u8 signal;
+	struct rate_info txrate;
 };
 
 /**
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 7a7a6c1..b5b1301 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -310,12 +310,35 @@ static void sta_set_sinfo(struct sta_info *sta, struct 
station_info *sinfo)
 
 	sinfo->filled = STATION_INFO_INACTIVE_TIME |
 			STATION_INFO_RX_BYTES |
-			STATION_INFO_TX_BYTES;
+			STATION_INFO_TX_BYTES |
+			STATION_INFO_TX_BITRATE;
 
 	sinfo->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx);
 	sinfo->rx_bytes = sta->rx_bytes;
 	sinfo->tx_bytes = sta->tx_bytes;
 
+	if (sta->local->hw.flags & IEEE80211_HW_SIGNAL_DBM) {
+		sinfo->filled |= STATION_INFO_SIGNAL;
+		sinfo->signal = sta->last_signal;
+	}
+
+	sinfo->txrate.flags = 0;
+	if (sta->last_tx_rate.flags & IEEE80211_TX_RC_MCS)
+		sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
+	if (sta->last_tx_rate.flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
+		sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
+	if (sta->last_tx_rate.flags & IEEE80211_TX_RC_SHORT_GI)
+		sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
+
+	if (!(sta->last_tx_rate.flags & IEEE80211_TX_RC_MCS)) {
+		struct ieee80211_supported_band *sband;
+		sband = sta->local->hw.wiphy->bands[
+				sta->local->hw.conf.channel->band];
+		sinfo->txrate.legacy =
+			sband->bitrates[sta->last_tx_rate.idx].bitrate;
+	} else
+		sinfo->txrate.mcs = sta->last_tx_rate.idx;
+
 	if (ieee80211_vif_is_mesh(&sdata->vif)) {
 #ifdef CONFIG_MAC80211_MESH
 		sinfo->filled |= STATION_INFO_LLID |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 9caee60..3f13928 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -1084,7 +1084,7 @@ static int nl80211_send_station(struct sk_buff *msg, u32 
pid, u32 seq,
 				u8 *mac_addr, struct station_info *sinfo)
 {
 	void *hdr;
-	struct nlattr *sinfoattr;
+	struct nlattr *sinfoattr, *txrate;
 
 	hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_STATION);
 	if (!hdr)
@@ -1114,7 +1114,28 @@ static int nl80211_send_station(struct sk_buff *msg, 
u32 pid, u32 seq,
 	if (sinfo->filled & STATION_INFO_PLINK_STATE)
 		NLA_PUT_U8(msg, NL80211_STA_INFO_PLINK_STATE,
 			    sinfo->plink_state);
+	if (sinfo->filled & STATION_INFO_SIGNAL)
+		NLA_PUT_U8(msg, NL80211_STA_INFO_SIGNAL,
+			   sinfo->signal);
+	if (sinfo->filled & STATION_INFO_TX_BITRATE) {
+		txrate = nla_nest_start(msg, NL80211_STA_INFO_TX_BITRATE);
+		if (!txrate)
+			goto nla_put_failure;
+
 
+		if (!(sinfo->txrate.flags & RATE_INFO_FLAGS_MCS))
+			NLA_PUT_U16(msg, NL80211_RATE_INFO_LEGACY,
+				    sinfo->txrate.legacy);
+		else
+			NLA_PUT_U8(msg, NL80211_RATE_INFO_MCS,
+				    sinfo->txrate.mcs);
+		if (sinfo->txrate.flags & RATE_INFO_FLAGS_40_MHZ_WIDTH)
+			NLA_PUT_FLAG(msg, NL80211_RATE_INFO_40_MHZ_WIDTH);
+		if (sinfo->txrate.flags & RATE_INFO_FLAGS_SHORT_GI)
+			NLA_PUT_FLAG(msg, NL80211_RATE_INFO_SHORT_GI);
+
+		nla_nest_end(msg, txrate);
+	}
 	nla_nest_end(msg, sinfoattr);
 
 	return genlmsg_end(msg, hdr);


[-- Attachment #1.2: nl80211ext_v9_1.patch --]
[-- Type: text/x-patch, Size: 7035 bytes --]

diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index 04d4516..56450b4 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -425,6 +425,30 @@ enum nl80211_sta_flags {
 };
 
 /**
+ * enum nl80211_rate_info - bitrate information
+ *
+ * These attribute types are used with %NL80211_STA_INFO_TXRATE
+ * when getting information about the bitrate of a station.
+ *
+ * @__NL80211_RATE_INFO_INVALID: attribute number 0 is reserved
+ * @NL80211_RATE_INFO_LEGACY: bitrate for 802.11abg (u16, 100kbit/s)
+ * @NL80211_RATE_INFO_MCS: mcs index for 802.11n (u8)
+ * @NL80211_RATE_INFO_40_MHZ_WIDTH: 40 Mhz dualchannel bitrate
+ * @NL80211_RATE_INFO_SHORT_GI: 400ns guard interval
+ */
+enum nl80211_rate_info {
+	__NL80211_RATE_INFO_INVALID,
+	NL80211_RATE_INFO_LEGACY,
+	NL80211_RATE_INFO_MCS,
+	NL80211_RATE_INFO_40_MHZ_WIDTH,
+	NL80211_RATE_INFO_SHORT_GI,
+
+	/* keep last */
+	__NL80211_RATE_INFO_AFTER_LAST,
+	NL80211_RATE_INFO_MAX = __NL80211_RATE_INFO_AFTER_LAST - 1
+};
+
+/**
  * enum nl80211_sta_info - station information
  *
  * These attribute types are used with %NL80211_ATTR_STA_INFO
@@ -436,6 +460,9 @@ enum nl80211_sta_flags {
  * @NL80211_STA_INFO_TX_BYTES: total transmitted bytes (u32, to this station)
  * @__NL80211_STA_INFO_AFTER_LAST: internal
  * @NL80211_STA_INFO_MAX: highest possible station info attribute
+ * @NL80211_STA_INFO_SIGNAL: signal strength of last received PPDU (u8, dBm)
+ * @NL80211_STA_INFO_TX_BITRATE: current unicast tx rate, nested attribute
+ * 	containing info as possible, see &enum nl80211_sta_info_txrate.
  */
 enum nl80211_sta_info {
 	__NL80211_STA_INFO_INVALID,
@@ -445,6 +472,8 @@ enum nl80211_sta_info {
 	NL80211_STA_INFO_LLID,
 	NL80211_STA_INFO_PLID,
 	NL80211_STA_INFO_PLINK_STATE,
+	NL80211_STA_INFO_SIGNAL,
+	NL80211_STA_INFO_TX_BITRATE,
 
 	/* keep last */
 	__NL80211_STA_INFO_AFTER_LAST,
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index a0c0bf1..d9ce51e 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -169,6 +169,9 @@ struct station_parameters {
  * @STATION_INFO_LLID: @llid filled
  * @STATION_INFO_PLID: @plid filled
  * @STATION_INFO_PLINK_STATE: @plink_state filled
+ * @STATION_INFO_SIGNAL: @signal filled
+ * @STATION_INFO_TX_BITRATE: @tx_bitrate fields are filled
+ *  (tx_bitrate, tx_bitrate_flags and tx_bitrate_mcs)
  */
 enum station_info_flags {
 	STATION_INFO_INACTIVE_TIME	= 1<<0,
@@ -177,6 +180,39 @@ enum station_info_flags {
 	STATION_INFO_LLID		= 1<<3,
 	STATION_INFO_PLID		= 1<<4,
 	STATION_INFO_PLINK_STATE	= 1<<5,
+	STATION_INFO_SIGNAL		= 1<<6,
+	STATION_INFO_TX_BITRATE		= 1<<7,
+};
+
+/**
+ * enum station_info_rate_flags - bitrate info flags
+ *
+ * Used by the driver to indicate the specific rate transmission
+ * type for 802.11n transmissions.
+ *
+ * @RATE_INFO_FLAGS_MCS: @tx_bitrate_mcs filled
+ * @RATE_INFO_FLAGS_40_MHZ_WIDTH: 40 Mhz width transmission
+ * @RATE_INFO_FLAGS_SHORT_GI: 400ns guard interval
+ */
+enum rate_info_flags {
+	RATE_INFO_FLAGS_MCS		= 1<<0,
+	RATE_INFO_FLAGS_40_MHZ_WIDTH	= 1<<1,
+	RATE_INFO_FLAGS_SHORT_GI	= 1<<2,
+};
+
+/**
+ * struct rate_info - bitrate information
+ *
+ * Information about a receiving or transmitting bitrate
+ *
+ * @flags: bitflag of flags from &enum rate_info_flags
+ * @mcs: mcs index if struct describes a 802.11n bitrate
+ * @legacy: bitrate in 100kbit/s for 802.11abg
+ */
+struct rate_info {
+	u8 flags;
+	u8 mcs;
+	u16 legacy;
 };
 
 /**
@@ -191,6 +227,8 @@ enum station_info_flags {
  * @llid: mesh local link id
  * @plid: mesh peer link id
  * @plink_state: mesh peer link state
+ * @signal: signal strength of last received package in dBm
+ * @txrate: current unicast bitrate to this station
  */
 struct station_info {
 	u32 filled;
@@ -200,6 +238,8 @@ struct station_info {
 	u16 llid;
 	u16 plid;
 	u8 plink_state;
+	u8 signal;
+	struct rate_info txrate;
 };
 
 /**
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 7a7a6c1..b5b1301 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -310,12 +310,35 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
 
 	sinfo->filled = STATION_INFO_INACTIVE_TIME |
 			STATION_INFO_RX_BYTES |
-			STATION_INFO_TX_BYTES;
+			STATION_INFO_TX_BYTES |
+			STATION_INFO_TX_BITRATE;
 
 	sinfo->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx);
 	sinfo->rx_bytes = sta->rx_bytes;
 	sinfo->tx_bytes = sta->tx_bytes;
 
+	if (sta->local->hw.flags & IEEE80211_HW_SIGNAL_DBM) {
+		sinfo->filled |= STATION_INFO_SIGNAL;
+		sinfo->signal = sta->last_signal;
+	}
+
+	sinfo->txrate.flags = 0;
+	if (sta->last_tx_rate.flags & IEEE80211_TX_RC_MCS)
+		sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
+	if (sta->last_tx_rate.flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
+		sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
+	if (sta->last_tx_rate.flags & IEEE80211_TX_RC_SHORT_GI)
+		sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
+
+	if (!(sta->last_tx_rate.flags & IEEE80211_TX_RC_MCS)) {
+		struct ieee80211_supported_band *sband;
+		sband = sta->local->hw.wiphy->bands[
+				sta->local->hw.conf.channel->band];
+		sinfo->txrate.legacy =
+			sband->bitrates[sta->last_tx_rate.idx].bitrate;
+	} else
+		sinfo->txrate.mcs = sta->last_tx_rate.idx;
+
 	if (ieee80211_vif_is_mesh(&sdata->vif)) {
 #ifdef CONFIG_MAC80211_MESH
 		sinfo->filled |= STATION_INFO_LLID |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 9caee60..3f13928 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -1084,7 +1084,7 @@ static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
 				u8 *mac_addr, struct station_info *sinfo)
 {
 	void *hdr;
-	struct nlattr *sinfoattr;
+	struct nlattr *sinfoattr, *txrate;
 
 	hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_STATION);
 	if (!hdr)
@@ -1114,7 +1114,28 @@ static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
 	if (sinfo->filled & STATION_INFO_PLINK_STATE)
 		NLA_PUT_U8(msg, NL80211_STA_INFO_PLINK_STATE,
 			    sinfo->plink_state);
+	if (sinfo->filled & STATION_INFO_SIGNAL)
+		NLA_PUT_U8(msg, NL80211_STA_INFO_SIGNAL,
+			   sinfo->signal);
+	if (sinfo->filled & STATION_INFO_TX_BITRATE) {
+		txrate = nla_nest_start(msg, NL80211_STA_INFO_TX_BITRATE);
+		if (!txrate)
+			goto nla_put_failure;
+
 
+		if (!(sinfo->txrate.flags & RATE_INFO_FLAGS_MCS))
+			NLA_PUT_U16(msg, NL80211_RATE_INFO_LEGACY,
+				    sinfo->txrate.legacy);
+		else
+			NLA_PUT_U8(msg, NL80211_RATE_INFO_MCS,
+				    sinfo->txrate.mcs);
+		if (sinfo->txrate.flags & RATE_INFO_FLAGS_40_MHZ_WIDTH)
+			NLA_PUT_FLAG(msg, NL80211_RATE_INFO_40_MHZ_WIDTH);
+		if (sinfo->txrate.flags & RATE_INFO_FLAGS_SHORT_GI)
+			NLA_PUT_FLAG(msg, NL80211_RATE_INFO_SHORT_GI);
+
+		nla_nest_end(msg, txrate);
+	}
 	nla_nest_end(msg, sinfoattr);
 
 	return genlmsg_end(msg, hdr);

[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 197 bytes --]

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

* [Patch 2/2 v2] Add signal strength and bandwith to nl80211station info
  2008-12-08 19:43                                                   ` Johannes Berg
  2008-12-09 19:50                                                     ` Henning Rogge
  2008-12-09 19:54                                                     ` [Patch 1/2 v2] " Henning Rogge
@ 2008-12-09 19:58                                                     ` Henning Rogge
  2008-12-09 21:19                                                       ` Johannes Berg
  2 siblings, 1 reply; 66+ messages in thread
From: Henning Rogge @ 2008-12-09 19:58 UTC (permalink / raw)
  To: Johannes Berg
  Cc: Luis R. Rodriguez, Henning Rogge, Luis Rodriguez,
	Marcel Holtmann, linux-wireless, nbd


[-- Attachment #1.1: Type: text/plain, Size: 2859 bytes --]

This patch adds the total transmission bitrate for adhoc station even for 
802.11n transmissions. It must be applied after the first patch of this 
series.

--------------------------
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index 56450b4..cc93e7a 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -431,14 +431,14 @@ enum nl80211_sta_flags {
  * when getting information about the bitrate of a station.
  *
  * @__NL80211_RATE_INFO_INVALID: attribute number 0 is reserved
- * @NL80211_RATE_INFO_LEGACY: bitrate for 802.11abg (u16, 100kbit/s)
+ * @NL80211_RATE_INFO_BITRATE: total bitrate (u16, 100kbit/s)
  * @NL80211_RATE_INFO_MCS: mcs index for 802.11n (u8)
  * @NL80211_RATE_INFO_40_MHZ_WIDTH: 40 Mhz dualchannel bitrate
  * @NL80211_RATE_INFO_SHORT_GI: 400ns guard interval
  */
 enum nl80211_rate_info {
 	__NL80211_RATE_INFO_INVALID,
-	NL80211_RATE_INFO_LEGACY,
+	NL80211_RATE_INFO_BITRATE,
 	NL80211_RATE_INFO_MCS,
 	NL80211_RATE_INFO_40_MHZ_WIDTH,
 	NL80211_RATE_INFO_SHORT_GI,
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 3f13928..63a4d08 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -1079,6 +1079,35 @@ static int parse_station_flags(struct nlattr *nla, u32 
*staflags)
 	return 0;
 }
 
+static u16 nl80211_calculate_bitrate(struct rate_info *rate)
+{
+	int modulation, streams, bitrate;
+
+	if (!(rate->flags & RATE_INFO_FLAGS_MCS))
+		return rate->legacy;
+
+	modulation = rate->mcs & 7;
+	streams = (rate->mcs >> 3) + 1;
+
+	bitrate = (rate->flags & RATE_INFO_FLAGS_40_MHZ_WIDTH) ?
+			13500000 : 6500000;
+
+	if (modulation < 4)
+		bitrate *= (modulation + 1);
+	else if (modulation == 4)
+		bitrate *= (modulation + 2);
+	else
+		bitrate *= (modulation + 3);
+
+	bitrate *= streams;
+
+	if (rate->flags & RATE_INFO_FLAGS_SHORT_GI)
+		bitrate = (bitrate / 9) * 10;
+
+	/* do NOT round down here */
+	return (bitrate + 50000) / 100000;
+}
+
 static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
 				int flags, struct net_device *dev,
 				u8 *mac_addr, struct station_info *sinfo)
@@ -1122,13 +1151,12 @@ static int nl80211_send_station(struct sk_buff *msg, 
u32 pid, u32 seq,
 		if (!txrate)
 			goto nla_put_failure;
 
-
-		if (!(sinfo->txrate.flags & RATE_INFO_FLAGS_MCS))
-			NLA_PUT_U16(msg, NL80211_RATE_INFO_LEGACY,
-				    sinfo->txrate.legacy);
-		else
+		NLA_PUT_U16(msg, NL80211_RATE_INFO_BITRATE,
+				nl80211_calculate_bitrate(&sinfo->txrate));
+		if (sinfo->txrate.flags & RATE_INFO_FLAGS_MCS)
 			NLA_PUT_U8(msg, NL80211_RATE_INFO_MCS,
 				    sinfo->txrate.mcs);
+
 		if (sinfo->txrate.flags & RATE_INFO_FLAGS_40_MHZ_WIDTH)
 			NLA_PUT_FLAG(msg, NL80211_RATE_INFO_40_MHZ_WIDTH);
 		if (sinfo->txrate.flags & RATE_INFO_FLAGS_SHORT_GI)


[-- Attachment #1.2: nl80211ext_v9_2.patch --]
[-- Type: text/x-patch, Size: 2664 bytes --]

diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index 56450b4..cc93e7a 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -431,14 +431,14 @@ enum nl80211_sta_flags {
  * when getting information about the bitrate of a station.
  *
  * @__NL80211_RATE_INFO_INVALID: attribute number 0 is reserved
- * @NL80211_RATE_INFO_LEGACY: bitrate for 802.11abg (u16, 100kbit/s)
+ * @NL80211_RATE_INFO_BITRATE: total bitrate (u16, 100kbit/s)
  * @NL80211_RATE_INFO_MCS: mcs index for 802.11n (u8)
  * @NL80211_RATE_INFO_40_MHZ_WIDTH: 40 Mhz dualchannel bitrate
  * @NL80211_RATE_INFO_SHORT_GI: 400ns guard interval
  */
 enum nl80211_rate_info {
 	__NL80211_RATE_INFO_INVALID,
-	NL80211_RATE_INFO_LEGACY,
+	NL80211_RATE_INFO_BITRATE,
 	NL80211_RATE_INFO_MCS,
 	NL80211_RATE_INFO_40_MHZ_WIDTH,
 	NL80211_RATE_INFO_SHORT_GI,
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 3f13928..63a4d08 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -1079,6 +1079,35 @@ static int parse_station_flags(struct nlattr *nla, u32 *staflags)
 	return 0;
 }
 
+static u16 nl80211_calculate_bitrate(struct rate_info *rate)
+{
+	int modulation, streams, bitrate;
+
+	if (!(rate->flags & RATE_INFO_FLAGS_MCS))
+		return rate->legacy;
+
+	modulation = rate->mcs & 7;
+	streams = (rate->mcs >> 3) + 1;
+
+	bitrate = (rate->flags & RATE_INFO_FLAGS_40_MHZ_WIDTH) ?
+			13500000 : 6500000;
+
+	if (modulation < 4)
+		bitrate *= (modulation + 1);
+	else if (modulation == 4)
+		bitrate *= (modulation + 2);
+	else
+		bitrate *= (modulation + 3);
+
+	bitrate *= streams;
+
+	if (rate->flags & RATE_INFO_FLAGS_SHORT_GI)
+		bitrate = (bitrate / 9) * 10;
+
+	/* do NOT round down here */
+	return (bitrate + 50000) / 100000;
+}
+
 static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
 				int flags, struct net_device *dev,
 				u8 *mac_addr, struct station_info *sinfo)
@@ -1122,13 +1151,12 @@ static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
 		if (!txrate)
 			goto nla_put_failure;
 
-
-		if (!(sinfo->txrate.flags & RATE_INFO_FLAGS_MCS))
-			NLA_PUT_U16(msg, NL80211_RATE_INFO_LEGACY,
-				    sinfo->txrate.legacy);
-		else
+		NLA_PUT_U16(msg, NL80211_RATE_INFO_BITRATE,
+				nl80211_calculate_bitrate(&sinfo->txrate));
+		if (sinfo->txrate.flags & RATE_INFO_FLAGS_MCS)
 			NLA_PUT_U8(msg, NL80211_RATE_INFO_MCS,
 				    sinfo->txrate.mcs);
+
 		if (sinfo->txrate.flags & RATE_INFO_FLAGS_40_MHZ_WIDTH)
 			NLA_PUT_FLAG(msg, NL80211_RATE_INFO_40_MHZ_WIDTH);
 		if (sinfo->txrate.flags & RATE_INFO_FLAGS_SHORT_GI)

[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 197 bytes --]

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

* Re: [PATCH 1/2] Add signal strength and bandwith to nl80211station info
  2008-12-09 19:50                                                     ` Henning Rogge
@ 2008-12-09 21:16                                                       ` Johannes Berg
  2008-12-10  6:53                                                         ` Henning Rogge
  0 siblings, 1 reply; 66+ messages in thread
From: Johannes Berg @ 2008-12-09 21:16 UTC (permalink / raw)
  To: Henning Rogge
  Cc: Luis R. Rodriguez, Henning Rogge, Luis Rodriguez,
	Marcel Holtmann, linux-wireless, nbd

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

On Tue, 2008-12-09 at 20:50 +0100, Henning Rogge wrote:
> On Monday 08 December 2008 20:43:35 you wrote:
> > And on your second patch:
> > > +static u16 nl80211_calculate_bitrate(struct rate_info *rate)
> > > +{
> > > +       int modulation, streams, bitrate;
> > > +
> > > +       if (!(rate->flags & RATE_INFO_FLAGS_MCS))
> > > +               return rate->legacy;
> > > +
> > > +       modulation = rate->mcs & 7;
> > > +       streams = rate->mcs >> 3;
> 
> > I don't think this gives correct results for MCS rates 32 through 76,
> > does it? It should at least not calculate anything then. If we did it in
> > userspace then programs could also actually calculate the correct rate
> > as a float, rather than this approximation. Not that it'll matter, I
> > guess. Doesn't anybody know how to do the actual calculation?

> It had a small type (corrected in the new patches), but I think the values are 
> good. I have attached a test programm to this mail that outputs the bandwith 
> values calculated by the function.

No, that's the thing, for 32 through 76 the calculated values are
totally wrong, that isn't a logical extension of the scheme, MCS 73 for
20 MHz for example is:

four streams, using 64-qam, 64-qam, 16-qam, qpsk with a coding rate of
3/4 for a net bitrate of 195.0 MBits

johannes

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

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

* Re: [Patch 2/2 v2] Add signal strength and bandwith to nl80211station info
  2008-12-09 19:58                                                     ` [Patch 2/2 " Henning Rogge
@ 2008-12-09 21:19                                                       ` Johannes Berg
  0 siblings, 0 replies; 66+ messages in thread
From: Johannes Berg @ 2008-12-09 21:19 UTC (permalink / raw)
  To: Henning Rogge
  Cc: Luis R. Rodriguez, Henning Rogge, Luis Rodriguez,
	Marcel Holtmann, linux-wireless, nbd

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

On Tue, 2008-12-09 at 20:58 +0100, Henning Rogge wrote:

> -		if (!(sinfo->txrate.flags & RATE_INFO_FLAGS_MCS))
> -			NLA_PUT_U16(msg, NL80211_RATE_INFO_LEGACY,
> -				    sinfo->txrate.legacy);
> -		else
> +		NLA_PUT_U16(msg, NL80211_RATE_INFO_BITRATE,
> +				nl80211_calculate_bitrate(&sinfo->txrate));

If you do:

if (sinfo->txrate.flags & RATE_INFO_FLAGS_MCS) {
	if (sinfo->txrate.mcs < 32)
		NLA_PUT_U16(msg, ..., calculate());
} else
	NLA_PUT_U16(msg, ..., legacy);


and add a big comment to the calculate function that it only works for
MCS < 32, I'm fine with it.

johannes

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

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

* Re: [PATCH 1/2] Add signal strength and bandwith to nl80211station info
  2008-12-09 21:16                                                       ` Johannes Berg
@ 2008-12-10  6:53                                                         ` Henning Rogge
  2008-12-10  9:05                                                           ` Johannes Berg
  0 siblings, 1 reply; 66+ messages in thread
From: Henning Rogge @ 2008-12-10  6:53 UTC (permalink / raw)
  To: Johannes Berg
  Cc: Henning Rogge, Luis R. Rodriguez, Luis Rodriguez,
	Marcel Holtmann, linux-wireless, nbd

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

Am Tuesday 09 December 2008 22:16:12 schrieb Johannes Berg:
> No, that's the thing, for 32 through 76 the calculated values are
> totally wrong, that isn't a logical extension of the scheme, MCS 73 for
> 20 MHz for example is:
>
> four streams, using 64-qam, 64-qam, 16-qam, qpsk with a coding rate of
> 3/4 for a net bitrate of 195.0 MBits

Maybe you can just post the whole mcs 32-76 table, so I can look at it. I can 
only work with the values in the wiki, and at the moment the calculation 
matchs them very well.

Henning

*************************************************
Diplom Informatiker Henning Rogge
Forschungsgesellschaft für
Angewandte Naturwissenschaften e. V. (FGAN) 
Neuenahrer Str. 20, 53343 Wachtberg, Germany
Tel.: 0049 (0)228 9435-961
Fax: 0049 (0)228 9435-685
E-Mail: rogge@fgan.de
Web: www.fgan.de
************************************************
Sitz der Gesellschaft: Bonn
Registergericht: Amtsgericht Bonn VR 2530
Vorstand: Dr. rer. nat. Ralf Dornhaus (Vors.), Prof. Dr. Joachim Ender 
(Stellv.)


[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 197 bytes --]

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

* Re: [PATCH 1/2] Add signal strength and bandwith to nl80211station info
  2008-12-10  6:53                                                         ` Henning Rogge
@ 2008-12-10  9:05                                                           ` Johannes Berg
  2008-12-10 17:40                                                             ` Henning Rogge
  0 siblings, 1 reply; 66+ messages in thread
From: Johannes Berg @ 2008-12-10  9:05 UTC (permalink / raw)
  To: Henning Rogge
  Cc: Henning Rogge, Luis R. Rodriguez, Luis Rodriguez,
	Marcel Holtmann, linux-wireless, nbd

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

On Wed, 2008-12-10 at 07:53 +0100, Henning Rogge wrote:
> Am Tuesday 09 December 2008 22:16:12 schrieb Johannes Berg:
> > No, that's the thing, for 32 through 76 the calculated values are
> > totally wrong, that isn't a logical extension of the scheme, MCS 73 for
> > 20 MHz for example is:
> >
> > four streams, using 64-qam, 64-qam, 16-qam, qpsk with a coding rate of
> > 3/4 for a net bitrate of 195.0 MBits
> 
> Maybe you can just post the whole mcs 32-76 table, so I can look at it. I can 
> only work with the values in the wiki, and at the moment the calculation 
> matchs them very well.

Uh huh, it's a huge table, and very irregular. Not very inclined to copy
that right now. What's wrong with deferring it until somebody actually
implements these rates?

johannes

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

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

* Re: [PATCH 1/2] Add signal strength and bandwith to nl80211station info
  2008-12-10  9:05                                                           ` Johannes Berg
@ 2008-12-10 17:40                                                             ` Henning Rogge
  2008-12-10 20:45                                                               ` Johannes Berg
  0 siblings, 1 reply; 66+ messages in thread
From: Henning Rogge @ 2008-12-10 17:40 UTC (permalink / raw)
  To: Johannes Berg
  Cc: Henning Rogge, Luis R. Rodriguez, Luis Rodriguez,
	Marcel Holtmann, linux-wireless, nbd


[-- Attachment #1.1: Type: text/plain, Size: 3514 bytes --]

On Wednesday 10 December 2008 10:05:50 Johannes Berg wrote:
> Uh huh, it's a huge table, and very irregular. Not very inclined to copy
> that right now. What's wrong with deferring it until somebody actually
> implements these rates?

Okay... I will try to implement a complete version of the function when I get 
access to the table... here is a modified patch with two warnings about the 
missing datarates. It will return 0 for mcs >= 32.

Just a question, did someone with 802.11n hardware test this patches ? I hope 
I will have some hardware myself at the end of the year, but at the moment 
it's untested.

Henning

--------------------------
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index 56450b4..cc93e7a 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -431,14 +431,14 @@ enum nl80211_sta_flags {
  * when getting information about the bitrate of a station.
  *
  * @__NL80211_RATE_INFO_INVALID: attribute number 0 is reserved
- * @NL80211_RATE_INFO_LEGACY: bitrate for 802.11abg (u16, 100kbit/s)
+ * @NL80211_RATE_INFO_BITRATE: total bitrate (u16, 100kbit/s)
  * @NL80211_RATE_INFO_MCS: mcs index for 802.11n (u8)
  * @NL80211_RATE_INFO_40_MHZ_WIDTH: 40 Mhz dualchannel bitrate
  * @NL80211_RATE_INFO_SHORT_GI: 400ns guard interval
  */
 enum nl80211_rate_info {
 	__NL80211_RATE_INFO_INVALID,
-	NL80211_RATE_INFO_LEGACY,
+	NL80211_RATE_INFO_BITRATE,
 	NL80211_RATE_INFO_MCS,
 	NL80211_RATE_INFO_40_MHZ_WIDTH,
 	NL80211_RATE_INFO_SHORT_GI,
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 3f13928..643dcc1 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -1079,6 +1079,39 @@ static int parse_station_flags(struct nlattr *nla, u32 
*staflags)
 	return 0;
 }
 
+static u16 nl80211_calculate_bitrate(struct rate_info *rate)
+{
+	int modulation, streams, bitrate;
+
+	if (!(rate->flags & RATE_INFO_FLAGS_MCS))
+		return rate->legacy;
+
+	/* the formula below does only work for MCS values smaller than 32 */
+	if (rate->mcs >= 32)
+		return 0;
+
+	modulation = rate->mcs & 7;
+	streams = (rate->mcs >> 3) + 1;
+
+	bitrate = (rate->flags & RATE_INFO_FLAGS_40_MHZ_WIDTH) ?
+			13500000 : 6500000;
+
+	if (modulation < 4)
+		bitrate *= (modulation + 1);
+	else if (modulation == 4)
+		bitrate *= (modulation + 2);
+	else
+		bitrate *= (modulation + 3);
+
+	bitrate *= streams;
+
+	if (rate->flags & RATE_INFO_FLAGS_SHORT_GI)
+		bitrate = (bitrate / 9) * 10;
+
+	/* do NOT round down here */
+	return (bitrate + 50000) / 100000;
+}
+
 static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
 				int flags, struct net_device *dev,
 				u8 *mac_addr, struct station_info *sinfo)
@@ -1122,13 +1155,13 @@ static int nl80211_send_station(struct sk_buff *msg, 
u32 pid, u32 seq,
 		if (!txrate)
 			goto nla_put_failure;
 
-
-		if (!(sinfo->txrate.flags & RATE_INFO_FLAGS_MCS))
-			NLA_PUT_U16(msg, NL80211_RATE_INFO_LEGACY,
-				    sinfo->txrate.legacy);
-		else
+		/* nl80211_calculate_bitrate will return 0 for mcs >= 32 */
+		NLA_PUT_U16(msg, NL80211_RATE_INFO_BITRATE,
+				nl80211_calculate_bitrate(&sinfo->txrate));
+		if (sinfo->txrate.flags & RATE_INFO_FLAGS_MCS)
 			NLA_PUT_U8(msg, NL80211_RATE_INFO_MCS,
 				    sinfo->txrate.mcs);
+
 		if (sinfo->txrate.flags & RATE_INFO_FLAGS_40_MHZ_WIDTH)
 			NLA_PUT_FLAG(msg, NL80211_RATE_INFO_40_MHZ_WIDTH);
 		if (sinfo->txrate.flags & RATE_INFO_FLAGS_SHORT_GI)


[-- Attachment #1.2: nl80211ext_v10_2.patch --]
[-- Type: text/x-patch, Size: 2842 bytes --]

diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index 56450b4..cc93e7a 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -431,14 +431,14 @@ enum nl80211_sta_flags {
  * when getting information about the bitrate of a station.
  *
  * @__NL80211_RATE_INFO_INVALID: attribute number 0 is reserved
- * @NL80211_RATE_INFO_LEGACY: bitrate for 802.11abg (u16, 100kbit/s)
+ * @NL80211_RATE_INFO_BITRATE: total bitrate (u16, 100kbit/s)
  * @NL80211_RATE_INFO_MCS: mcs index for 802.11n (u8)
  * @NL80211_RATE_INFO_40_MHZ_WIDTH: 40 Mhz dualchannel bitrate
  * @NL80211_RATE_INFO_SHORT_GI: 400ns guard interval
  */
 enum nl80211_rate_info {
 	__NL80211_RATE_INFO_INVALID,
-	NL80211_RATE_INFO_LEGACY,
+	NL80211_RATE_INFO_BITRATE,
 	NL80211_RATE_INFO_MCS,
 	NL80211_RATE_INFO_40_MHZ_WIDTH,
 	NL80211_RATE_INFO_SHORT_GI,
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 3f13928..643dcc1 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -1079,6 +1079,39 @@ static int parse_station_flags(struct nlattr *nla, u32 *staflags)
 	return 0;
 }
 
+static u16 nl80211_calculate_bitrate(struct rate_info *rate)
+{
+	int modulation, streams, bitrate;
+
+	if (!(rate->flags & RATE_INFO_FLAGS_MCS))
+		return rate->legacy;
+
+	/* the formula below does only work for MCS values smaller than 32 */
+	if (rate->mcs >= 32)
+		return 0;
+
+	modulation = rate->mcs & 7;
+	streams = (rate->mcs >> 3) + 1;
+
+	bitrate = (rate->flags & RATE_INFO_FLAGS_40_MHZ_WIDTH) ?
+			13500000 : 6500000;
+
+	if (modulation < 4)
+		bitrate *= (modulation + 1);
+	else if (modulation == 4)
+		bitrate *= (modulation + 2);
+	else
+		bitrate *= (modulation + 3);
+
+	bitrate *= streams;
+
+	if (rate->flags & RATE_INFO_FLAGS_SHORT_GI)
+		bitrate = (bitrate / 9) * 10;
+
+	/* do NOT round down here */
+	return (bitrate + 50000) / 100000;
+}
+
 static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
 				int flags, struct net_device *dev,
 				u8 *mac_addr, struct station_info *sinfo)
@@ -1122,13 +1155,13 @@ static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
 		if (!txrate)
 			goto nla_put_failure;
 
-
-		if (!(sinfo->txrate.flags & RATE_INFO_FLAGS_MCS))
-			NLA_PUT_U16(msg, NL80211_RATE_INFO_LEGACY,
-				    sinfo->txrate.legacy);
-		else
+		/* nl80211_calculate_bitrate will return 0 for mcs >= 32 */
+		NLA_PUT_U16(msg, NL80211_RATE_INFO_BITRATE,
+				nl80211_calculate_bitrate(&sinfo->txrate));
+		if (sinfo->txrate.flags & RATE_INFO_FLAGS_MCS)
 			NLA_PUT_U8(msg, NL80211_RATE_INFO_MCS,
 				    sinfo->txrate.mcs);
+
 		if (sinfo->txrate.flags & RATE_INFO_FLAGS_40_MHZ_WIDTH)
 			NLA_PUT_FLAG(msg, NL80211_RATE_INFO_40_MHZ_WIDTH);
 		if (sinfo->txrate.flags & RATE_INFO_FLAGS_SHORT_GI)

[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 197 bytes --]

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

* Re: [PATCH 1/2] Add signal strength and bandwith to nl80211station info
  2008-12-10 17:40                                                             ` Henning Rogge
@ 2008-12-10 20:45                                                               ` Johannes Berg
  2008-12-10 20:58                                                                 ` Henning Rogge
  0 siblings, 1 reply; 66+ messages in thread
From: Johannes Berg @ 2008-12-10 20:45 UTC (permalink / raw)
  To: Henning Rogge
  Cc: Henning Rogge, Luis R. Rodriguez, Luis Rodriguez,
	Marcel Holtmann, linux-wireless, nbd

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

On Wed, 2008-12-10 at 18:40 +0100, Henning Rogge wrote:
> On Wednesday 10 December 2008 10:05:50 Johannes Berg wrote:
> > Uh huh, it's a huge table, and very irregular. Not very inclined to copy
> > that right now. What's wrong with deferring it until somebody actually
> > implements these rates?
> 
> Okay... I will try to implement a complete version of the function when I get 
> access to the table... here is a modified patch with two warnings about the 
> missing datarates. It will return 0 for mcs >= 32.

Can you do what I asked for instead and not include the attribute when
it has a bogus value?

Thanks,
Johannes

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

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

* Re: [PATCH 1/2] Add signal strength and bandwith to nl80211station info
  2008-12-10 20:45                                                               ` Johannes Berg
@ 2008-12-10 20:58                                                                 ` Henning Rogge
  2008-12-10 21:01                                                                   ` Johannes Berg
  0 siblings, 1 reply; 66+ messages in thread
From: Henning Rogge @ 2008-12-10 20:58 UTC (permalink / raw)
  To: Johannes Berg
  Cc: Henning Rogge, Luis R. Rodriguez, Luis Rodriguez,
	Marcel Holtmann, linux-wireless, nbd


[-- Attachment #1.1: Type: text/plain, Size: 3233 bytes --]

On Wednesday 10 December 2008 21:45:37 Johannes Berg wrote:
> On Wed, 2008-12-10 at 18:40 +0100, Henning Rogge wrote:
> Can you do what I asked for instead and not include the attribute when
> it has a bogus value?
I agree, that was a stupid thing...

Henning
-------------------------------
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index 56450b4..cc93e7a 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -431,14 +431,14 @@ enum nl80211_sta_flags {
  * when getting information about the bitrate of a station.
  *
  * @__NL80211_RATE_INFO_INVALID: attribute number 0 is reserved
- * @NL80211_RATE_INFO_LEGACY: bitrate for 802.11abg (u16, 100kbit/s)
+ * @NL80211_RATE_INFO_BITRATE: total bitrate (u16, 100kbit/s)
  * @NL80211_RATE_INFO_MCS: mcs index for 802.11n (u8)
  * @NL80211_RATE_INFO_40_MHZ_WIDTH: 40 Mhz dualchannel bitrate
  * @NL80211_RATE_INFO_SHORT_GI: 400ns guard interval
  */
 enum nl80211_rate_info {
 	__NL80211_RATE_INFO_INVALID,
-	NL80211_RATE_INFO_LEGACY,
+	NL80211_RATE_INFO_BITRATE,
 	NL80211_RATE_INFO_MCS,
 	NL80211_RATE_INFO_40_MHZ_WIDTH,
 	NL80211_RATE_INFO_SHORT_GI,
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 3f13928..4797b47 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -1079,12 +1079,46 @@ static int parse_station_flags(struct nlattr *nla, u32 
*staflags)
 	return 0;
 }
 
+static u16 nl80211_calculate_bitrate(struct rate_info *rate)
+{
+	int modulation, streams, bitrate;
+
+	if (!(rate->flags & RATE_INFO_FLAGS_MCS))
+		return rate->legacy;
+
+	/* the formula below does only work for MCS values smaller than 32 */
+	if (rate->mcs >= 32)
+		return 0;
+
+	modulation = rate->mcs & 7;
+	streams = (rate->mcs >> 3) + 1;
+
+	bitrate = (rate->flags & RATE_INFO_FLAGS_40_MHZ_WIDTH) ?
+			13500000 : 6500000;
+
+	if (modulation < 4)
+		bitrate *= (modulation + 1);
+	else if (modulation == 4)
+		bitrate *= (modulation + 2);
+	else
+		bitrate *= (modulation + 3);
+
+	bitrate *= streams;
+
+	if (rate->flags & RATE_INFO_FLAGS_SHORT_GI)
+		bitrate = (bitrate / 9) * 10;
+
+	/* do NOT round down here */
+	return (bitrate + 50000) / 100000;
+}
+
 static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
 				int flags, struct net_device *dev,
 				u8 *mac_addr, struct station_info *sinfo)
 {
 	void *hdr;
 	struct nlattr *sinfoattr, *txrate;
+	u16 bitrate;
 
 	hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_STATION);
 	if (!hdr)
@@ -1122,11 +1156,12 @@ static int nl80211_send_station(struct sk_buff *msg, 
u32 pid, u32 seq,
 		if (!txrate)
 			goto nla_put_failure;
 
+		/* nl80211_calculate_bitrate will return 0 for mcs >= 32 */
+		bitrate = nl80211_calculate_bitrate(&sinfo->txrate);
+		if (bitrate > 0)
+			NLA_PUT_U16(msg, NL80211_RATE_INFO_BITRATE, bitrate);
 
-		if (!(sinfo->txrate.flags & RATE_INFO_FLAGS_MCS))
-			NLA_PUT_U16(msg, NL80211_RATE_INFO_LEGACY,
-				    sinfo->txrate.legacy);
-		else
+		if (sinfo->txrate.flags & RATE_INFO_FLAGS_MCS)
 			NLA_PUT_U8(msg, NL80211_RATE_INFO_MCS,
 				    sinfo->txrate.mcs);
 		if (sinfo->txrate.flags & RATE_INFO_FLAGS_40_MHZ_WIDTH)


[-- Attachment #1.2: nl80211ext_v11_2.patch --]
[-- Type: text/x-patch, Size: 2927 bytes --]

diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index 56450b4..cc93e7a 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -431,14 +431,14 @@ enum nl80211_sta_flags {
  * when getting information about the bitrate of a station.
  *
  * @__NL80211_RATE_INFO_INVALID: attribute number 0 is reserved
- * @NL80211_RATE_INFO_LEGACY: bitrate for 802.11abg (u16, 100kbit/s)
+ * @NL80211_RATE_INFO_BITRATE: total bitrate (u16, 100kbit/s)
  * @NL80211_RATE_INFO_MCS: mcs index for 802.11n (u8)
  * @NL80211_RATE_INFO_40_MHZ_WIDTH: 40 Mhz dualchannel bitrate
  * @NL80211_RATE_INFO_SHORT_GI: 400ns guard interval
  */
 enum nl80211_rate_info {
 	__NL80211_RATE_INFO_INVALID,
-	NL80211_RATE_INFO_LEGACY,
+	NL80211_RATE_INFO_BITRATE,
 	NL80211_RATE_INFO_MCS,
 	NL80211_RATE_INFO_40_MHZ_WIDTH,
 	NL80211_RATE_INFO_SHORT_GI,
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 3f13928..4797b47 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -1079,12 +1079,46 @@ static int parse_station_flags(struct nlattr *nla, u32 *staflags)
 	return 0;
 }
 
+static u16 nl80211_calculate_bitrate(struct rate_info *rate)
+{
+	int modulation, streams, bitrate;
+
+	if (!(rate->flags & RATE_INFO_FLAGS_MCS))
+		return rate->legacy;
+
+	/* the formula below does only work for MCS values smaller than 32 */
+	if (rate->mcs >= 32)
+		return 0;
+
+	modulation = rate->mcs & 7;
+	streams = (rate->mcs >> 3) + 1;
+
+	bitrate = (rate->flags & RATE_INFO_FLAGS_40_MHZ_WIDTH) ?
+			13500000 : 6500000;
+
+	if (modulation < 4)
+		bitrate *= (modulation + 1);
+	else if (modulation == 4)
+		bitrate *= (modulation + 2);
+	else
+		bitrate *= (modulation + 3);
+
+	bitrate *= streams;
+
+	if (rate->flags & RATE_INFO_FLAGS_SHORT_GI)
+		bitrate = (bitrate / 9) * 10;
+
+	/* do NOT round down here */
+	return (bitrate + 50000) / 100000;
+}
+
 static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
 				int flags, struct net_device *dev,
 				u8 *mac_addr, struct station_info *sinfo)
 {
 	void *hdr;
 	struct nlattr *sinfoattr, *txrate;
+	u16 bitrate;
 
 	hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_STATION);
 	if (!hdr)
@@ -1122,11 +1156,12 @@ static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
 		if (!txrate)
 			goto nla_put_failure;
 
+		/* nl80211_calculate_bitrate will return 0 for mcs >= 32 */
+		bitrate = nl80211_calculate_bitrate(&sinfo->txrate);
+		if (bitrate > 0)
+			NLA_PUT_U16(msg, NL80211_RATE_INFO_BITRATE, bitrate);
 
-		if (!(sinfo->txrate.flags & RATE_INFO_FLAGS_MCS))
-			NLA_PUT_U16(msg, NL80211_RATE_INFO_LEGACY,
-				    sinfo->txrate.legacy);
-		else
+		if (sinfo->txrate.flags & RATE_INFO_FLAGS_MCS)
 			NLA_PUT_U8(msg, NL80211_RATE_INFO_MCS,
 				    sinfo->txrate.mcs);
 		if (sinfo->txrate.flags & RATE_INFO_FLAGS_40_MHZ_WIDTH)

[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 197 bytes --]

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

* Re: [PATCH 1/2] Add signal strength and bandwith to nl80211station info
  2008-12-10 20:58                                                                 ` Henning Rogge
@ 2008-12-10 21:01                                                                   ` Johannes Berg
  2008-12-11 17:07                                                                     ` [Patch] nl80211: " Henning Rogge
  0 siblings, 1 reply; 66+ messages in thread
From: Johannes Berg @ 2008-12-10 21:01 UTC (permalink / raw)
  To: Henning Rogge
  Cc: Henning Rogge, Luis R. Rodriguez, Luis Rodriguez,
	Marcel Holtmann, linux-wireless, nbd

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

On Wed, 2008-12-10 at 21:58 +0100, Henning Rogge wrote:
> On Wednesday 10 December 2008 21:45:37 Johannes Berg wrote:
> > On Wed, 2008-12-10 at 18:40 +0100, Henning Rogge wrote:
> > Can you do what I asked for instead and not include the attribute when
> > it has a bogus value?
> I agree, that was a stupid thing...

Now merge it all into one patch, and I think we're good :)

> Henning
> -------------------------------
> diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
> index 56450b4..cc93e7a 100644
> --- a/include/linux/nl80211.h
> +++ b/include/linux/nl80211.h
> @@ -431,14 +431,14 @@ enum nl80211_sta_flags {
>   * when getting information about the bitrate of a station.
>   *
>   * @__NL80211_RATE_INFO_INVALID: attribute number 0 is reserved
> - * @NL80211_RATE_INFO_LEGACY: bitrate for 802.11abg (u16, 100kbit/s)
> + * @NL80211_RATE_INFO_BITRATE: total bitrate (u16, 100kbit/s)
>   * @NL80211_RATE_INFO_MCS: mcs index for 802.11n (u8)
>   * @NL80211_RATE_INFO_40_MHZ_WIDTH: 40 Mhz dualchannel bitrate
>   * @NL80211_RATE_INFO_SHORT_GI: 400ns guard interval
>   */
>  enum nl80211_rate_info {
>  	__NL80211_RATE_INFO_INVALID,
> -	NL80211_RATE_INFO_LEGACY,
> +	NL80211_RATE_INFO_BITRATE,
>  	NL80211_RATE_INFO_MCS,
>  	NL80211_RATE_INFO_40_MHZ_WIDTH,
>  	NL80211_RATE_INFO_SHORT_GI,
> diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
> index 3f13928..4797b47 100644
> --- a/net/wireless/nl80211.c
> +++ b/net/wireless/nl80211.c
> @@ -1079,12 +1079,46 @@ static int parse_station_flags(struct nlattr *nla, u32 
> *staflags)
>  	return 0;
>  }
>  
> +static u16 nl80211_calculate_bitrate(struct rate_info *rate)
> +{
> +	int modulation, streams, bitrate;
> +
> +	if (!(rate->flags & RATE_INFO_FLAGS_MCS))
> +		return rate->legacy;
> +
> +	/* the formula below does only work for MCS values smaller than 32 */
> +	if (rate->mcs >= 32)
> +		return 0;
> +
> +	modulation = rate->mcs & 7;
> +	streams = (rate->mcs >> 3) + 1;
> +
> +	bitrate = (rate->flags & RATE_INFO_FLAGS_40_MHZ_WIDTH) ?
> +			13500000 : 6500000;
> +
> +	if (modulation < 4)
> +		bitrate *= (modulation + 1);
> +	else if (modulation == 4)
> +		bitrate *= (modulation + 2);
> +	else
> +		bitrate *= (modulation + 3);
> +
> +	bitrate *= streams;
> +
> +	if (rate->flags & RATE_INFO_FLAGS_SHORT_GI)
> +		bitrate = (bitrate / 9) * 10;
> +
> +	/* do NOT round down here */
> +	return (bitrate + 50000) / 100000;
> +}
> +
>  static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
>  				int flags, struct net_device *dev,
>  				u8 *mac_addr, struct station_info *sinfo)
>  {
>  	void *hdr;
>  	struct nlattr *sinfoattr, *txrate;
> +	u16 bitrate;
>  
>  	hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_STATION);
>  	if (!hdr)
> @@ -1122,11 +1156,12 @@ static int nl80211_send_station(struct sk_buff *msg, 
> u32 pid, u32 seq,
>  		if (!txrate)
>  			goto nla_put_failure;
>  
> +		/* nl80211_calculate_bitrate will return 0 for mcs >= 32 */
> +		bitrate = nl80211_calculate_bitrate(&sinfo->txrate);
> +		if (bitrate > 0)
> +			NLA_PUT_U16(msg, NL80211_RATE_INFO_BITRATE, bitrate);
>  
> -		if (!(sinfo->txrate.flags & RATE_INFO_FLAGS_MCS))
> -			NLA_PUT_U16(msg, NL80211_RATE_INFO_LEGACY,
> -				    sinfo->txrate.legacy);
> -		else
> +		if (sinfo->txrate.flags & RATE_INFO_FLAGS_MCS)
>  			NLA_PUT_U8(msg, NL80211_RATE_INFO_MCS,
>  				    sinfo->txrate.mcs);
>  		if (sinfo->txrate.flags & RATE_INFO_FLAGS_40_MHZ_WIDTH)
> 

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

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

* [Patch] nl80211: Add signal strength and bandwith to nl80211station info
  2008-12-10 21:01                                                                   ` Johannes Berg
@ 2008-12-11 17:07                                                                     ` Henning Rogge
  2008-12-11 17:24                                                                       ` Johannes Berg
  0 siblings, 1 reply; 66+ messages in thread
From: Henning Rogge @ 2008-12-11 17:07 UTC (permalink / raw)
  To: Johannes Berg
  Cc: Henning Rogge, Luis R. Rodriguez, Luis Rodriguez,
	Marcel Holtmann, linux-wireless, nbd


[-- Attachment #1.1: Type: text/plain, Size: 8236 bytes --]

This patch adds signal strength and transmission bitrate
to the station_info of nl80211.

Signed-off-by: Henning Rogge <rogge@fgan.de>
---
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index 04d4516..cc93e7a 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -425,6 +425,30 @@ enum nl80211_sta_flags {
 };
 
 /**
+ * enum nl80211_rate_info - bitrate information
+ *
+ * These attribute types are used with %NL80211_STA_INFO_TXRATE
+ * when getting information about the bitrate of a station.
+ *
+ * @__NL80211_RATE_INFO_INVALID: attribute number 0 is reserved
+ * @NL80211_RATE_INFO_BITRATE: total bitrate (u16, 100kbit/s)
+ * @NL80211_RATE_INFO_MCS: mcs index for 802.11n (u8)
+ * @NL80211_RATE_INFO_40_MHZ_WIDTH: 40 Mhz dualchannel bitrate
+ * @NL80211_RATE_INFO_SHORT_GI: 400ns guard interval
+ */
+enum nl80211_rate_info {
+	__NL80211_RATE_INFO_INVALID,
+	NL80211_RATE_INFO_BITRATE,
+	NL80211_RATE_INFO_MCS,
+	NL80211_RATE_INFO_40_MHZ_WIDTH,
+	NL80211_RATE_INFO_SHORT_GI,
+
+	/* keep last */
+	__NL80211_RATE_INFO_AFTER_LAST,
+	NL80211_RATE_INFO_MAX = __NL80211_RATE_INFO_AFTER_LAST - 1
+};
+
+/**
  * enum nl80211_sta_info - station information
  *
  * These attribute types are used with %NL80211_ATTR_STA_INFO
@@ -436,6 +460,9 @@ enum nl80211_sta_flags {
  * @NL80211_STA_INFO_TX_BYTES: total transmitted bytes (u32, to this station)
  * @__NL80211_STA_INFO_AFTER_LAST: internal
  * @NL80211_STA_INFO_MAX: highest possible station info attribute
+ * @NL80211_STA_INFO_SIGNAL: signal strength of last received PPDU (u8, dBm)
+ * @NL80211_STA_INFO_TX_BITRATE: current unicast tx rate, nested attribute
+ * 	containing info as possible, see &enum nl80211_sta_info_txrate.
  */
 enum nl80211_sta_info {
 	__NL80211_STA_INFO_INVALID,
@@ -445,6 +472,8 @@ enum nl80211_sta_info {
 	NL80211_STA_INFO_LLID,
 	NL80211_STA_INFO_PLID,
 	NL80211_STA_INFO_PLINK_STATE,
+	NL80211_STA_INFO_SIGNAL,
+	NL80211_STA_INFO_TX_BITRATE,
 
 	/* keep last */
 	__NL80211_STA_INFO_AFTER_LAST,
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index a0c0bf1..d9ce51e 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -169,6 +169,9 @@ struct station_parameters {
  * @STATION_INFO_LLID: @llid filled
  * @STATION_INFO_PLID: @plid filled
  * @STATION_INFO_PLINK_STATE: @plink_state filled
+ * @STATION_INFO_SIGNAL: @signal filled
+ * @STATION_INFO_TX_BITRATE: @tx_bitrate fields are filled
+ *  (tx_bitrate, tx_bitrate_flags and tx_bitrate_mcs)
  */
 enum station_info_flags {
 	STATION_INFO_INACTIVE_TIME	= 1<<0,
@@ -177,6 +180,39 @@ enum station_info_flags {
 	STATION_INFO_LLID		= 1<<3,
 	STATION_INFO_PLID		= 1<<4,
 	STATION_INFO_PLINK_STATE	= 1<<5,
+	STATION_INFO_SIGNAL		= 1<<6,
+	STATION_INFO_TX_BITRATE		= 1<<7,
+};
+
+/**
+ * enum station_info_rate_flags - bitrate info flags
+ *
+ * Used by the driver to indicate the specific rate transmission
+ * type for 802.11n transmissions.
+ *
+ * @RATE_INFO_FLAGS_MCS: @tx_bitrate_mcs filled
+ * @RATE_INFO_FLAGS_40_MHZ_WIDTH: 40 Mhz width transmission
+ * @RATE_INFO_FLAGS_SHORT_GI: 400ns guard interval
+ */
+enum rate_info_flags {
+	RATE_INFO_FLAGS_MCS		= 1<<0,
+	RATE_INFO_FLAGS_40_MHZ_WIDTH	= 1<<1,
+	RATE_INFO_FLAGS_SHORT_GI	= 1<<2,
+};
+
+/**
+ * struct rate_info - bitrate information
+ *
+ * Information about a receiving or transmitting bitrate
+ *
+ * @flags: bitflag of flags from &enum rate_info_flags
+ * @mcs: mcs index if struct describes a 802.11n bitrate
+ * @legacy: bitrate in 100kbit/s for 802.11abg
+ */
+struct rate_info {
+	u8 flags;
+	u8 mcs;
+	u16 legacy;
 };
 
 /**
@@ -191,6 +227,8 @@ enum station_info_flags {
  * @llid: mesh local link id
  * @plid: mesh peer link id
  * @plink_state: mesh peer link state
+ * @signal: signal strength of last received package in dBm
+ * @txrate: current unicast bitrate to this station
  */
 struct station_info {
 	u32 filled;
@@ -200,6 +238,8 @@ struct station_info {
 	u16 llid;
 	u16 plid;
 	u8 plink_state;
+	u8 signal;
+	struct rate_info txrate;
 };
 
 /**
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 7912eb1..6778fe0 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -310,12 +310,35 @@ static void sta_set_sinfo(struct sta_info *sta, struct 
station_info *sinfo)
 
 	sinfo->filled = STATION_INFO_INACTIVE_TIME |
 			STATION_INFO_RX_BYTES |
-			STATION_INFO_TX_BYTES;
+			STATION_INFO_TX_BYTES |
+			STATION_INFO_TX_BITRATE;
 
 	sinfo->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx);
 	sinfo->rx_bytes = sta->rx_bytes;
 	sinfo->tx_bytes = sta->tx_bytes;
 
+	if (sta->local->hw.flags & IEEE80211_HW_SIGNAL_DBM) {
+		sinfo->filled |= STATION_INFO_SIGNAL;
+		sinfo->signal = sta->last_signal;
+	}
+
+	sinfo->txrate.flags = 0;
+	if (sta->last_tx_rate.flags & IEEE80211_TX_RC_MCS)
+		sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
+	if (sta->last_tx_rate.flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
+		sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
+	if (sta->last_tx_rate.flags & IEEE80211_TX_RC_SHORT_GI)
+		sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
+
+	if (!(sta->last_tx_rate.flags & IEEE80211_TX_RC_MCS)) {
+		struct ieee80211_supported_band *sband;
+		sband = sta->local->hw.wiphy->bands[
+				sta->local->hw.conf.channel->band];
+		sinfo->txrate.legacy =
+			sband->bitrates[sta->last_tx_rate.idx].bitrate;
+	} else
+		sinfo->txrate.mcs = sta->last_tx_rate.idx;
+
 	if (ieee80211_vif_is_mesh(&sdata->vif)) {
 #ifdef CONFIG_MAC80211_MESH
 		sinfo->filled |= STATION_INFO_LLID |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 4335f76..93c9b98 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -1091,12 +1091,46 @@ static int parse_station_flags(struct nlattr *nla, u32 
*staflags)
 	return 0;
 }
 
+static u16 nl80211_calculate_bitrate(struct rate_info *rate)
+{
+	int modulation, streams, bitrate;
+
+	if (!(rate->flags & RATE_INFO_FLAGS_MCS))
+		return rate->legacy;
+
+	/* the formula below does only work for MCS values smaller than 32 */
+	if (rate->mcs >= 32)
+		return 0;
+
+	modulation = rate->mcs & 7;
+	streams = (rate->mcs >> 3) + 1;
+
+	bitrate = (rate->flags & RATE_INFO_FLAGS_40_MHZ_WIDTH) ?
+			13500000 : 6500000;
+
+	if (modulation < 4)
+		bitrate *= (modulation + 1);
+	else if (modulation == 4)
+		bitrate *= (modulation + 2);
+	else
+		bitrate *= (modulation + 3);
+
+	bitrate *= streams;
+
+	if (rate->flags & RATE_INFO_FLAGS_SHORT_GI)
+		bitrate = (bitrate / 9) * 10;
+
+	/* do NOT round down here */
+	return (bitrate + 50000) / 100000;
+}
+
 static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
 				int flags, struct net_device *dev,
 				u8 *mac_addr, struct station_info *sinfo)
 {
 	void *hdr;
-	struct nlattr *sinfoattr;
+	struct nlattr *sinfoattr, *txrate;
+	u16 bitrate;
 
 	hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_STATION);
 	if (!hdr)
@@ -1126,7 +1160,29 @@ static int nl80211_send_station(struct sk_buff *msg, 
u32 pid, u32 seq,
 	if (sinfo->filled & STATION_INFO_PLINK_STATE)
 		NLA_PUT_U8(msg, NL80211_STA_INFO_PLINK_STATE,
 			    sinfo->plink_state);
+	if (sinfo->filled & STATION_INFO_SIGNAL)
+		NLA_PUT_U8(msg, NL80211_STA_INFO_SIGNAL,
+			   sinfo->signal);
+	if (sinfo->filled & STATION_INFO_TX_BITRATE) {
+		txrate = nla_nest_start(msg, NL80211_STA_INFO_TX_BITRATE);
+		if (!txrate)
+			goto nla_put_failure;
+
+		/* nl80211_calculate_bitrate will return 0 for mcs >= 32 */
+		bitrate = nl80211_calculate_bitrate(&sinfo->txrate);
+		if (bitrate > 0)
+			NLA_PUT_U16(msg, NL80211_RATE_INFO_BITRATE, bitrate);
 
+		if (sinfo->txrate.flags & RATE_INFO_FLAGS_MCS)
+			NLA_PUT_U8(msg, NL80211_RATE_INFO_MCS,
+				    sinfo->txrate.mcs);
+		if (sinfo->txrate.flags & RATE_INFO_FLAGS_40_MHZ_WIDTH)
+			NLA_PUT_FLAG(msg, NL80211_RATE_INFO_40_MHZ_WIDTH);
+		if (sinfo->txrate.flags & RATE_INFO_FLAGS_SHORT_GI)
+			NLA_PUT_FLAG(msg, NL80211_RATE_INFO_SHORT_GI);
+
+		nla_nest_end(msg, txrate);
+	}
 	nla_nest_end(msg, sinfoattr);
 
 	return genlmsg_end(msg, hdr);


[-- Attachment #1.2: nl80211ext_v12.patch --]
[-- Type: text/x-patch, Size: 8228 bytes --]

This patch adds signal strength and transmission bitrate
to the station_info of nl80211.

Signed-off-by: Henning Rogge <rogge@fgan.de>
---
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index 04d4516..cc93e7a 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -425,6 +425,30 @@ enum nl80211_sta_flags {
 };
 
 /**
+ * enum nl80211_rate_info - bitrate information
+ *
+ * These attribute types are used with %NL80211_STA_INFO_TXRATE
+ * when getting information about the bitrate of a station.
+ *
+ * @__NL80211_RATE_INFO_INVALID: attribute number 0 is reserved
+ * @NL80211_RATE_INFO_BITRATE: total bitrate (u16, 100kbit/s)
+ * @NL80211_RATE_INFO_MCS: mcs index for 802.11n (u8)
+ * @NL80211_RATE_INFO_40_MHZ_WIDTH: 40 Mhz dualchannel bitrate
+ * @NL80211_RATE_INFO_SHORT_GI: 400ns guard interval
+ */
+enum nl80211_rate_info {
+	__NL80211_RATE_INFO_INVALID,
+	NL80211_RATE_INFO_BITRATE,
+	NL80211_RATE_INFO_MCS,
+	NL80211_RATE_INFO_40_MHZ_WIDTH,
+	NL80211_RATE_INFO_SHORT_GI,
+
+	/* keep last */
+	__NL80211_RATE_INFO_AFTER_LAST,
+	NL80211_RATE_INFO_MAX = __NL80211_RATE_INFO_AFTER_LAST - 1
+};
+
+/**
  * enum nl80211_sta_info - station information
  *
  * These attribute types are used with %NL80211_ATTR_STA_INFO
@@ -436,6 +460,9 @@ enum nl80211_sta_flags {
  * @NL80211_STA_INFO_TX_BYTES: total transmitted bytes (u32, to this station)
  * @__NL80211_STA_INFO_AFTER_LAST: internal
  * @NL80211_STA_INFO_MAX: highest possible station info attribute
+ * @NL80211_STA_INFO_SIGNAL: signal strength of last received PPDU (u8, dBm)
+ * @NL80211_STA_INFO_TX_BITRATE: current unicast tx rate, nested attribute
+ * 	containing info as possible, see &enum nl80211_sta_info_txrate.
  */
 enum nl80211_sta_info {
 	__NL80211_STA_INFO_INVALID,
@@ -445,6 +472,8 @@ enum nl80211_sta_info {
 	NL80211_STA_INFO_LLID,
 	NL80211_STA_INFO_PLID,
 	NL80211_STA_INFO_PLINK_STATE,
+	NL80211_STA_INFO_SIGNAL,
+	NL80211_STA_INFO_TX_BITRATE,
 
 	/* keep last */
 	__NL80211_STA_INFO_AFTER_LAST,
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index a0c0bf1..d9ce51e 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -169,6 +169,9 @@ struct station_parameters {
  * @STATION_INFO_LLID: @llid filled
  * @STATION_INFO_PLID: @plid filled
  * @STATION_INFO_PLINK_STATE: @plink_state filled
+ * @STATION_INFO_SIGNAL: @signal filled
+ * @STATION_INFO_TX_BITRATE: @tx_bitrate fields are filled
+ *  (tx_bitrate, tx_bitrate_flags and tx_bitrate_mcs)
  */
 enum station_info_flags {
 	STATION_INFO_INACTIVE_TIME	= 1<<0,
@@ -177,6 +180,39 @@ enum station_info_flags {
 	STATION_INFO_LLID		= 1<<3,
 	STATION_INFO_PLID		= 1<<4,
 	STATION_INFO_PLINK_STATE	= 1<<5,
+	STATION_INFO_SIGNAL		= 1<<6,
+	STATION_INFO_TX_BITRATE		= 1<<7,
+};
+
+/**
+ * enum station_info_rate_flags - bitrate info flags
+ *
+ * Used by the driver to indicate the specific rate transmission
+ * type for 802.11n transmissions.
+ *
+ * @RATE_INFO_FLAGS_MCS: @tx_bitrate_mcs filled
+ * @RATE_INFO_FLAGS_40_MHZ_WIDTH: 40 Mhz width transmission
+ * @RATE_INFO_FLAGS_SHORT_GI: 400ns guard interval
+ */
+enum rate_info_flags {
+	RATE_INFO_FLAGS_MCS		= 1<<0,
+	RATE_INFO_FLAGS_40_MHZ_WIDTH	= 1<<1,
+	RATE_INFO_FLAGS_SHORT_GI	= 1<<2,
+};
+
+/**
+ * struct rate_info - bitrate information
+ *
+ * Information about a receiving or transmitting bitrate
+ *
+ * @flags: bitflag of flags from &enum rate_info_flags
+ * @mcs: mcs index if struct describes a 802.11n bitrate
+ * @legacy: bitrate in 100kbit/s for 802.11abg
+ */
+struct rate_info {
+	u8 flags;
+	u8 mcs;
+	u16 legacy;
 };
 
 /**
@@ -191,6 +227,8 @@ enum station_info_flags {
  * @llid: mesh local link id
  * @plid: mesh peer link id
  * @plink_state: mesh peer link state
+ * @signal: signal strength of last received package in dBm
+ * @txrate: current unicast bitrate to this station
  */
 struct station_info {
 	u32 filled;
@@ -200,6 +238,8 @@ struct station_info {
 	u16 llid;
 	u16 plid;
 	u8 plink_state;
+	u8 signal;
+	struct rate_info txrate;
 };
 
 /**
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 7912eb1..6778fe0 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -310,12 +310,35 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
 
 	sinfo->filled = STATION_INFO_INACTIVE_TIME |
 			STATION_INFO_RX_BYTES |
-			STATION_INFO_TX_BYTES;
+			STATION_INFO_TX_BYTES |
+			STATION_INFO_TX_BITRATE;
 
 	sinfo->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx);
 	sinfo->rx_bytes = sta->rx_bytes;
 	sinfo->tx_bytes = sta->tx_bytes;
 
+	if (sta->local->hw.flags & IEEE80211_HW_SIGNAL_DBM) {
+		sinfo->filled |= STATION_INFO_SIGNAL;
+		sinfo->signal = sta->last_signal;
+	}
+
+	sinfo->txrate.flags = 0;
+	if (sta->last_tx_rate.flags & IEEE80211_TX_RC_MCS)
+		sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
+	if (sta->last_tx_rate.flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
+		sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
+	if (sta->last_tx_rate.flags & IEEE80211_TX_RC_SHORT_GI)
+		sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
+
+	if (!(sta->last_tx_rate.flags & IEEE80211_TX_RC_MCS)) {
+		struct ieee80211_supported_band *sband;
+		sband = sta->local->hw.wiphy->bands[
+				sta->local->hw.conf.channel->band];
+		sinfo->txrate.legacy =
+			sband->bitrates[sta->last_tx_rate.idx].bitrate;
+	} else
+		sinfo->txrate.mcs = sta->last_tx_rate.idx;
+
 	if (ieee80211_vif_is_mesh(&sdata->vif)) {
 #ifdef CONFIG_MAC80211_MESH
 		sinfo->filled |= STATION_INFO_LLID |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 4335f76..93c9b98 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -1091,12 +1091,46 @@ static int parse_station_flags(struct nlattr *nla, u32 *staflags)
 	return 0;
 }
 
+static u16 nl80211_calculate_bitrate(struct rate_info *rate)
+{
+	int modulation, streams, bitrate;
+
+	if (!(rate->flags & RATE_INFO_FLAGS_MCS))
+		return rate->legacy;
+
+	/* the formula below does only work for MCS values smaller than 32 */
+	if (rate->mcs >= 32)
+		return 0;
+
+	modulation = rate->mcs & 7;
+	streams = (rate->mcs >> 3) + 1;
+
+	bitrate = (rate->flags & RATE_INFO_FLAGS_40_MHZ_WIDTH) ?
+			13500000 : 6500000;
+
+	if (modulation < 4)
+		bitrate *= (modulation + 1);
+	else if (modulation == 4)
+		bitrate *= (modulation + 2);
+	else
+		bitrate *= (modulation + 3);
+
+	bitrate *= streams;
+
+	if (rate->flags & RATE_INFO_FLAGS_SHORT_GI)
+		bitrate = (bitrate / 9) * 10;
+
+	/* do NOT round down here */
+	return (bitrate + 50000) / 100000;
+}
+
 static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
 				int flags, struct net_device *dev,
 				u8 *mac_addr, struct station_info *sinfo)
 {
 	void *hdr;
-	struct nlattr *sinfoattr;
+	struct nlattr *sinfoattr, *txrate;
+	u16 bitrate;
 
 	hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_STATION);
 	if (!hdr)
@@ -1126,7 +1160,29 @@ static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
 	if (sinfo->filled & STATION_INFO_PLINK_STATE)
 		NLA_PUT_U8(msg, NL80211_STA_INFO_PLINK_STATE,
 			    sinfo->plink_state);
+	if (sinfo->filled & STATION_INFO_SIGNAL)
+		NLA_PUT_U8(msg, NL80211_STA_INFO_SIGNAL,
+			   sinfo->signal);
+	if (sinfo->filled & STATION_INFO_TX_BITRATE) {
+		txrate = nla_nest_start(msg, NL80211_STA_INFO_TX_BITRATE);
+		if (!txrate)
+			goto nla_put_failure;
+
+		/* nl80211_calculate_bitrate will return 0 for mcs >= 32 */
+		bitrate = nl80211_calculate_bitrate(&sinfo->txrate);
+		if (bitrate > 0)
+			NLA_PUT_U16(msg, NL80211_RATE_INFO_BITRATE, bitrate);
 
+		if (sinfo->txrate.flags & RATE_INFO_FLAGS_MCS)
+			NLA_PUT_U8(msg, NL80211_RATE_INFO_MCS,
+				    sinfo->txrate.mcs);
+		if (sinfo->txrate.flags & RATE_INFO_FLAGS_40_MHZ_WIDTH)
+			NLA_PUT_FLAG(msg, NL80211_RATE_INFO_40_MHZ_WIDTH);
+		if (sinfo->txrate.flags & RATE_INFO_FLAGS_SHORT_GI)
+			NLA_PUT_FLAG(msg, NL80211_RATE_INFO_SHORT_GI);
+
+		nla_nest_end(msg, txrate);
+	}
 	nla_nest_end(msg, sinfoattr);
 
 	return genlmsg_end(msg, hdr);

[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 197 bytes --]

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

* Re: [Patch] nl80211: Add signal strength and bandwith to nl80211station info
  2008-12-11 17:07                                                                     ` [Patch] nl80211: " Henning Rogge
@ 2008-12-11 17:24                                                                       ` Johannes Berg
  2008-12-11 18:02                                                                         ` Henning Rogge
  0 siblings, 1 reply; 66+ messages in thread
From: Johannes Berg @ 2008-12-11 17:24 UTC (permalink / raw)
  To: Henning Rogge
  Cc: Henning Rogge, Luis R. Rodriguez, Luis Rodriguez,
	Marcel Holtmann, linux-wireless, nbd

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

On Thu, 2008-12-11 at 18:07 +0100, Henning Rogge wrote:
> This patch adds signal strength and transmission bitrate
> to the station_info of nl80211.

Ok, this looks good, except a few minor things:

> + * @signal: signal strength of last received package in dBm

I still want to change the docs to read "packet" here ;)

> + * @txrate: current unicast bitrate to this station
>   */
>  struct station_info {
>  	u32 filled;
> @@ -200,6 +238,8 @@ struct station_info {
>  	u16 llid;
>  	u16 plid;
>  	u8 plink_state;
> +	u8 signal;

and I think a u8 isn't the right type. It should be s8.

Can you also send me the corresponding iw patch?

johannes

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

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

* Re: [Patch] nl80211: Add signal strength and bandwith to nl80211station info
  2008-12-11 17:24                                                                       ` Johannes Berg
@ 2008-12-11 18:02                                                                         ` Henning Rogge
  2008-12-11 18:14                                                                           ` Johannes Berg
  0 siblings, 1 reply; 66+ messages in thread
From: Henning Rogge @ 2008-12-11 18:02 UTC (permalink / raw)
  To: Johannes Berg
  Cc: Henning Rogge, Luis R. Rodriguez, Luis Rodriguez,
	Marcel Holtmann, linux-wireless, nbd


[-- Attachment #1.1: Type: text/plain, Size: 9174 bytes --]

On Thursday 11 December 2008 18:24:08 Johannes Berg wrote:
> Ok, this looks good, except a few minor things:
> > + * @signal: signal strength of last received package in dBm
>
> I still want to change the docs to read "packet" here ;)
>
> > + * @txrate: current unicast bitrate to this station
> >   */
> >  struct station_info {
> >  	u32 filled;
> > @@ -200,6 +238,8 @@ struct station_info {
> >  	u16 llid;
> >  	u16 plid;
> >  	u8 plink_state;
> > +	u8 signal;
>
> and I think a u8 isn't the right type. It should be s8.
Okay... I have included a casting to s8 into cfg.c so everyone is warned... 
the original signal field in the sta_info struct is an int, but this structure 
is used by the drivers so I don't want to touch it.

> Can you also send me the corresponding iw patch?
Have to write a modified one, I will post it later this evening I think.

Henning
----------------------------------------
This patch adds signal strength and transmission bitrate
to the station_info of nl80211.

Signed-off-by: Henning Rogge <rogge@fgan.de>
---
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index 04d4516..cc93e7a 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -425,6 +425,30 @@ enum nl80211_sta_flags {
 };
 
 /**
+ * enum nl80211_rate_info - bitrate information
+ *
+ * These attribute types are used with %NL80211_STA_INFO_TXRATE
+ * when getting information about the bitrate of a station.
+ *
+ * @__NL80211_RATE_INFO_INVALID: attribute number 0 is reserved
+ * @NL80211_RATE_INFO_BITRATE: total bitrate (u16, 100kbit/s)
+ * @NL80211_RATE_INFO_MCS: mcs index for 802.11n (u8)
+ * @NL80211_RATE_INFO_40_MHZ_WIDTH: 40 Mhz dualchannel bitrate
+ * @NL80211_RATE_INFO_SHORT_GI: 400ns guard interval
+ */
+enum nl80211_rate_info {
+	__NL80211_RATE_INFO_INVALID,
+	NL80211_RATE_INFO_BITRATE,
+	NL80211_RATE_INFO_MCS,
+	NL80211_RATE_INFO_40_MHZ_WIDTH,
+	NL80211_RATE_INFO_SHORT_GI,
+
+	/* keep last */
+	__NL80211_RATE_INFO_AFTER_LAST,
+	NL80211_RATE_INFO_MAX = __NL80211_RATE_INFO_AFTER_LAST - 1
+};
+
+/**
  * enum nl80211_sta_info - station information
  *
  * These attribute types are used with %NL80211_ATTR_STA_INFO
@@ -436,6 +460,9 @@ enum nl80211_sta_flags {
  * @NL80211_STA_INFO_TX_BYTES: total transmitted bytes (u32, to this station)
  * @__NL80211_STA_INFO_AFTER_LAST: internal
  * @NL80211_STA_INFO_MAX: highest possible station info attribute
+ * @NL80211_STA_INFO_SIGNAL: signal strength of last received PPDU (u8, dBm)
+ * @NL80211_STA_INFO_TX_BITRATE: current unicast tx rate, nested attribute
+ * 	containing info as possible, see &enum nl80211_sta_info_txrate.
  */
 enum nl80211_sta_info {
 	__NL80211_STA_INFO_INVALID,
@@ -445,6 +472,8 @@ enum nl80211_sta_info {
 	NL80211_STA_INFO_LLID,
 	NL80211_STA_INFO_PLID,
 	NL80211_STA_INFO_PLINK_STATE,
+	NL80211_STA_INFO_SIGNAL,
+	NL80211_STA_INFO_TX_BITRATE,
 
 	/* keep last */
 	__NL80211_STA_INFO_AFTER_LAST,
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index a0c0bf1..65e03ac 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -169,6 +169,9 @@ struct station_parameters {
  * @STATION_INFO_LLID: @llid filled
  * @STATION_INFO_PLID: @plid filled
  * @STATION_INFO_PLINK_STATE: @plink_state filled
+ * @STATION_INFO_SIGNAL: @signal filled
+ * @STATION_INFO_TX_BITRATE: @tx_bitrate fields are filled
+ *  (tx_bitrate, tx_bitrate_flags and tx_bitrate_mcs)
  */
 enum station_info_flags {
 	STATION_INFO_INACTIVE_TIME	= 1<<0,
@@ -177,6 +180,39 @@ enum station_info_flags {
 	STATION_INFO_LLID		= 1<<3,
 	STATION_INFO_PLID		= 1<<4,
 	STATION_INFO_PLINK_STATE	= 1<<5,
+	STATION_INFO_SIGNAL		= 1<<6,
+	STATION_INFO_TX_BITRATE		= 1<<7,
+};
+
+/**
+ * enum station_info_rate_flags - bitrate info flags
+ *
+ * Used by the driver to indicate the specific rate transmission
+ * type for 802.11n transmissions.
+ *
+ * @RATE_INFO_FLAGS_MCS: @tx_bitrate_mcs filled
+ * @RATE_INFO_FLAGS_40_MHZ_WIDTH: 40 Mhz width transmission
+ * @RATE_INFO_FLAGS_SHORT_GI: 400ns guard interval
+ */
+enum rate_info_flags {
+	RATE_INFO_FLAGS_MCS		= 1<<0,
+	RATE_INFO_FLAGS_40_MHZ_WIDTH	= 1<<1,
+	RATE_INFO_FLAGS_SHORT_GI	= 1<<2,
+};
+
+/**
+ * struct rate_info - bitrate information
+ *
+ * Information about a receiving or transmitting bitrate
+ *
+ * @flags: bitflag of flags from &enum rate_info_flags
+ * @mcs: mcs index if struct describes a 802.11n bitrate
+ * @legacy: bitrate in 100kbit/s for 802.11abg
+ */
+struct rate_info {
+	u8 flags;
+	u8 mcs;
+	u16 legacy;
 };
 
 /**
@@ -191,6 +227,8 @@ enum station_info_flags {
  * @llid: mesh local link id
  * @plid: mesh peer link id
  * @plink_state: mesh peer link state
+ * @signal: signal strength of last received packet in dBm
+ * @txrate: current unicast bitrate to this station
  */
 struct station_info {
 	u32 filled;
@@ -200,6 +238,8 @@ struct station_info {
 	u16 llid;
 	u16 plid;
 	u8 plink_state;
+	s8 signal;
+	struct rate_info txrate;
 };
 
 /**
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 7912eb1..23b5eea 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -310,12 +310,35 @@ static void sta_set_sinfo(struct sta_info *sta, struct 
station_info *sinfo)
 
 	sinfo->filled = STATION_INFO_INACTIVE_TIME |
 			STATION_INFO_RX_BYTES |
-			STATION_INFO_TX_BYTES;
+			STATION_INFO_TX_BYTES |
+			STATION_INFO_TX_BITRATE;
 
 	sinfo->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx);
 	sinfo->rx_bytes = sta->rx_bytes;
 	sinfo->tx_bytes = sta->tx_bytes;
 
+	if (sta->local->hw.flags & IEEE80211_HW_SIGNAL_DBM) {
+		sinfo->filled |= STATION_INFO_SIGNAL;
+		sinfo->signal = (s8)sta->last_signal;
+	}
+
+	sinfo->txrate.flags = 0;
+	if (sta->last_tx_rate.flags & IEEE80211_TX_RC_MCS)
+		sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
+	if (sta->last_tx_rate.flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
+		sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
+	if (sta->last_tx_rate.flags & IEEE80211_TX_RC_SHORT_GI)
+		sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
+
+	if (!(sta->last_tx_rate.flags & IEEE80211_TX_RC_MCS)) {
+		struct ieee80211_supported_band *sband;
+		sband = sta->local->hw.wiphy->bands[
+				sta->local->hw.conf.channel->band];
+		sinfo->txrate.legacy =
+			sband->bitrates[sta->last_tx_rate.idx].bitrate;
+	} else
+		sinfo->txrate.mcs = sta->last_tx_rate.idx;
+
 	if (ieee80211_vif_is_mesh(&sdata->vif)) {
 #ifdef CONFIG_MAC80211_MESH
 		sinfo->filled |= STATION_INFO_LLID |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 4335f76..93c9b98 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -1091,12 +1091,46 @@ static int parse_station_flags(struct nlattr *nla, u32 
*staflags)
 	return 0;
 }
 
+static u16 nl80211_calculate_bitrate(struct rate_info *rate)
+{
+	int modulation, streams, bitrate;
+
+	if (!(rate->flags & RATE_INFO_FLAGS_MCS))
+		return rate->legacy;
+
+	/* the formula below does only work for MCS values smaller than 32 */
+	if (rate->mcs >= 32)
+		return 0;
+
+	modulation = rate->mcs & 7;
+	streams = (rate->mcs >> 3) + 1;
+
+	bitrate = (rate->flags & RATE_INFO_FLAGS_40_MHZ_WIDTH) ?
+			13500000 : 6500000;
+
+	if (modulation < 4)
+		bitrate *= (modulation + 1);
+	else if (modulation == 4)
+		bitrate *= (modulation + 2);
+	else
+		bitrate *= (modulation + 3);
+
+	bitrate *= streams;
+
+	if (rate->flags & RATE_INFO_FLAGS_SHORT_GI)
+		bitrate = (bitrate / 9) * 10;
+
+	/* do NOT round down here */
+	return (bitrate + 50000) / 100000;
+}
+
 static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
 				int flags, struct net_device *dev,
 				u8 *mac_addr, struct station_info *sinfo)
 {
 	void *hdr;
-	struct nlattr *sinfoattr;
+	struct nlattr *sinfoattr, *txrate;
+	u16 bitrate;
 
 	hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_STATION);
 	if (!hdr)
@@ -1126,7 +1160,29 @@ static int nl80211_send_station(struct sk_buff *msg, 
u32 pid, u32 seq,
 	if (sinfo->filled & STATION_INFO_PLINK_STATE)
 		NLA_PUT_U8(msg, NL80211_STA_INFO_PLINK_STATE,
 			    sinfo->plink_state);
+	if (sinfo->filled & STATION_INFO_SIGNAL)
+		NLA_PUT_U8(msg, NL80211_STA_INFO_SIGNAL,
+			   sinfo->signal);
+	if (sinfo->filled & STATION_INFO_TX_BITRATE) {
+		txrate = nla_nest_start(msg, NL80211_STA_INFO_TX_BITRATE);
+		if (!txrate)
+			goto nla_put_failure;
+
+		/* nl80211_calculate_bitrate will return 0 for mcs >= 32 */
+		bitrate = nl80211_calculate_bitrate(&sinfo->txrate);
+		if (bitrate > 0)
+			NLA_PUT_U16(msg, NL80211_RATE_INFO_BITRATE, bitrate);
 
+		if (sinfo->txrate.flags & RATE_INFO_FLAGS_MCS)
+			NLA_PUT_U8(msg, NL80211_RATE_INFO_MCS,
+				    sinfo->txrate.mcs);
+		if (sinfo->txrate.flags & RATE_INFO_FLAGS_40_MHZ_WIDTH)
+			NLA_PUT_FLAG(msg, NL80211_RATE_INFO_40_MHZ_WIDTH);
+		if (sinfo->txrate.flags & RATE_INFO_FLAGS_SHORT_GI)
+			NLA_PUT_FLAG(msg, NL80211_RATE_INFO_SHORT_GI);
+
+		nla_nest_end(msg, txrate);
+	}
 	nla_nest_end(msg, sinfoattr);
 
 	return genlmsg_end(msg, hdr);


[-- Attachment #1.2: nl80211ext_v13.patch --]
[-- Type: text/x-patch, Size: 8231 bytes --]

This patch adds signal strength and transmission bitrate
to the station_info of nl80211.

Signed-off-by: Henning Rogge <rogge@fgan.de>
---
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index 04d4516..cc93e7a 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -425,6 +425,30 @@ enum nl80211_sta_flags {
 };
 
 /**
+ * enum nl80211_rate_info - bitrate information
+ *
+ * These attribute types are used with %NL80211_STA_INFO_TXRATE
+ * when getting information about the bitrate of a station.
+ *
+ * @__NL80211_RATE_INFO_INVALID: attribute number 0 is reserved
+ * @NL80211_RATE_INFO_BITRATE: total bitrate (u16, 100kbit/s)
+ * @NL80211_RATE_INFO_MCS: mcs index for 802.11n (u8)
+ * @NL80211_RATE_INFO_40_MHZ_WIDTH: 40 Mhz dualchannel bitrate
+ * @NL80211_RATE_INFO_SHORT_GI: 400ns guard interval
+ */
+enum nl80211_rate_info {
+	__NL80211_RATE_INFO_INVALID,
+	NL80211_RATE_INFO_BITRATE,
+	NL80211_RATE_INFO_MCS,
+	NL80211_RATE_INFO_40_MHZ_WIDTH,
+	NL80211_RATE_INFO_SHORT_GI,
+
+	/* keep last */
+	__NL80211_RATE_INFO_AFTER_LAST,
+	NL80211_RATE_INFO_MAX = __NL80211_RATE_INFO_AFTER_LAST - 1
+};
+
+/**
  * enum nl80211_sta_info - station information
  *
  * These attribute types are used with %NL80211_ATTR_STA_INFO
@@ -436,6 +460,9 @@ enum nl80211_sta_flags {
  * @NL80211_STA_INFO_TX_BYTES: total transmitted bytes (u32, to this station)
  * @__NL80211_STA_INFO_AFTER_LAST: internal
  * @NL80211_STA_INFO_MAX: highest possible station info attribute
+ * @NL80211_STA_INFO_SIGNAL: signal strength of last received PPDU (u8, dBm)
+ * @NL80211_STA_INFO_TX_BITRATE: current unicast tx rate, nested attribute
+ * 	containing info as possible, see &enum nl80211_sta_info_txrate.
  */
 enum nl80211_sta_info {
 	__NL80211_STA_INFO_INVALID,
@@ -445,6 +472,8 @@ enum nl80211_sta_info {
 	NL80211_STA_INFO_LLID,
 	NL80211_STA_INFO_PLID,
 	NL80211_STA_INFO_PLINK_STATE,
+	NL80211_STA_INFO_SIGNAL,
+	NL80211_STA_INFO_TX_BITRATE,
 
 	/* keep last */
 	__NL80211_STA_INFO_AFTER_LAST,
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index a0c0bf1..65e03ac 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -169,6 +169,9 @@ struct station_parameters {
  * @STATION_INFO_LLID: @llid filled
  * @STATION_INFO_PLID: @plid filled
  * @STATION_INFO_PLINK_STATE: @plink_state filled
+ * @STATION_INFO_SIGNAL: @signal filled
+ * @STATION_INFO_TX_BITRATE: @tx_bitrate fields are filled
+ *  (tx_bitrate, tx_bitrate_flags and tx_bitrate_mcs)
  */
 enum station_info_flags {
 	STATION_INFO_INACTIVE_TIME	= 1<<0,
@@ -177,6 +180,39 @@ enum station_info_flags {
 	STATION_INFO_LLID		= 1<<3,
 	STATION_INFO_PLID		= 1<<4,
 	STATION_INFO_PLINK_STATE	= 1<<5,
+	STATION_INFO_SIGNAL		= 1<<6,
+	STATION_INFO_TX_BITRATE		= 1<<7,
+};
+
+/**
+ * enum station_info_rate_flags - bitrate info flags
+ *
+ * Used by the driver to indicate the specific rate transmission
+ * type for 802.11n transmissions.
+ *
+ * @RATE_INFO_FLAGS_MCS: @tx_bitrate_mcs filled
+ * @RATE_INFO_FLAGS_40_MHZ_WIDTH: 40 Mhz width transmission
+ * @RATE_INFO_FLAGS_SHORT_GI: 400ns guard interval
+ */
+enum rate_info_flags {
+	RATE_INFO_FLAGS_MCS		= 1<<0,
+	RATE_INFO_FLAGS_40_MHZ_WIDTH	= 1<<1,
+	RATE_INFO_FLAGS_SHORT_GI	= 1<<2,
+};
+
+/**
+ * struct rate_info - bitrate information
+ *
+ * Information about a receiving or transmitting bitrate
+ *
+ * @flags: bitflag of flags from &enum rate_info_flags
+ * @mcs: mcs index if struct describes a 802.11n bitrate
+ * @legacy: bitrate in 100kbit/s for 802.11abg
+ */
+struct rate_info {
+	u8 flags;
+	u8 mcs;
+	u16 legacy;
 };
 
 /**
@@ -191,6 +227,8 @@ enum station_info_flags {
  * @llid: mesh local link id
  * @plid: mesh peer link id
  * @plink_state: mesh peer link state
+ * @signal: signal strength of last received packet in dBm
+ * @txrate: current unicast bitrate to this station
  */
 struct station_info {
 	u32 filled;
@@ -200,6 +238,8 @@ struct station_info {
 	u16 llid;
 	u16 plid;
 	u8 plink_state;
+	s8 signal;
+	struct rate_info txrate;
 };
 
 /**
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 7912eb1..23b5eea 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -310,12 +310,35 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
 
 	sinfo->filled = STATION_INFO_INACTIVE_TIME |
 			STATION_INFO_RX_BYTES |
-			STATION_INFO_TX_BYTES;
+			STATION_INFO_TX_BYTES |
+			STATION_INFO_TX_BITRATE;
 
 	sinfo->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx);
 	sinfo->rx_bytes = sta->rx_bytes;
 	sinfo->tx_bytes = sta->tx_bytes;
 
+	if (sta->local->hw.flags & IEEE80211_HW_SIGNAL_DBM) {
+		sinfo->filled |= STATION_INFO_SIGNAL;
+		sinfo->signal = (s8)sta->last_signal;
+	}
+
+	sinfo->txrate.flags = 0;
+	if (sta->last_tx_rate.flags & IEEE80211_TX_RC_MCS)
+		sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
+	if (sta->last_tx_rate.flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
+		sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
+	if (sta->last_tx_rate.flags & IEEE80211_TX_RC_SHORT_GI)
+		sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
+
+	if (!(sta->last_tx_rate.flags & IEEE80211_TX_RC_MCS)) {
+		struct ieee80211_supported_band *sband;
+		sband = sta->local->hw.wiphy->bands[
+				sta->local->hw.conf.channel->band];
+		sinfo->txrate.legacy =
+			sband->bitrates[sta->last_tx_rate.idx].bitrate;
+	} else
+		sinfo->txrate.mcs = sta->last_tx_rate.idx;
+
 	if (ieee80211_vif_is_mesh(&sdata->vif)) {
 #ifdef CONFIG_MAC80211_MESH
 		sinfo->filled |= STATION_INFO_LLID |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 4335f76..93c9b98 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -1091,12 +1091,46 @@ static int parse_station_flags(struct nlattr *nla, u32 *staflags)
 	return 0;
 }
 
+static u16 nl80211_calculate_bitrate(struct rate_info *rate)
+{
+	int modulation, streams, bitrate;
+
+	if (!(rate->flags & RATE_INFO_FLAGS_MCS))
+		return rate->legacy;
+
+	/* the formula below does only work for MCS values smaller than 32 */
+	if (rate->mcs >= 32)
+		return 0;
+
+	modulation = rate->mcs & 7;
+	streams = (rate->mcs >> 3) + 1;
+
+	bitrate = (rate->flags & RATE_INFO_FLAGS_40_MHZ_WIDTH) ?
+			13500000 : 6500000;
+
+	if (modulation < 4)
+		bitrate *= (modulation + 1);
+	else if (modulation == 4)
+		bitrate *= (modulation + 2);
+	else
+		bitrate *= (modulation + 3);
+
+	bitrate *= streams;
+
+	if (rate->flags & RATE_INFO_FLAGS_SHORT_GI)
+		bitrate = (bitrate / 9) * 10;
+
+	/* do NOT round down here */
+	return (bitrate + 50000) / 100000;
+}
+
 static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
 				int flags, struct net_device *dev,
 				u8 *mac_addr, struct station_info *sinfo)
 {
 	void *hdr;
-	struct nlattr *sinfoattr;
+	struct nlattr *sinfoattr, *txrate;
+	u16 bitrate;
 
 	hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_STATION);
 	if (!hdr)
@@ -1126,7 +1160,29 @@ static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
 	if (sinfo->filled & STATION_INFO_PLINK_STATE)
 		NLA_PUT_U8(msg, NL80211_STA_INFO_PLINK_STATE,
 			    sinfo->plink_state);
+	if (sinfo->filled & STATION_INFO_SIGNAL)
+		NLA_PUT_U8(msg, NL80211_STA_INFO_SIGNAL,
+			   sinfo->signal);
+	if (sinfo->filled & STATION_INFO_TX_BITRATE) {
+		txrate = nla_nest_start(msg, NL80211_STA_INFO_TX_BITRATE);
+		if (!txrate)
+			goto nla_put_failure;
+
+		/* nl80211_calculate_bitrate will return 0 for mcs >= 32 */
+		bitrate = nl80211_calculate_bitrate(&sinfo->txrate);
+		if (bitrate > 0)
+			NLA_PUT_U16(msg, NL80211_RATE_INFO_BITRATE, bitrate);
 
+		if (sinfo->txrate.flags & RATE_INFO_FLAGS_MCS)
+			NLA_PUT_U8(msg, NL80211_RATE_INFO_MCS,
+				    sinfo->txrate.mcs);
+		if (sinfo->txrate.flags & RATE_INFO_FLAGS_40_MHZ_WIDTH)
+			NLA_PUT_FLAG(msg, NL80211_RATE_INFO_40_MHZ_WIDTH);
+		if (sinfo->txrate.flags & RATE_INFO_FLAGS_SHORT_GI)
+			NLA_PUT_FLAG(msg, NL80211_RATE_INFO_SHORT_GI);
+
+		nla_nest_end(msg, txrate);
+	}
 	nla_nest_end(msg, sinfoattr);
 
 	return genlmsg_end(msg, hdr);

[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 197 bytes --]

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

* Re: [Patch] nl80211: Add signal strength and bandwith to nl80211station info
  2008-12-11 18:02                                                                         ` Henning Rogge
@ 2008-12-11 18:14                                                                           ` Johannes Berg
  2008-12-11 18:22                                                                             ` Henning Rogge
  0 siblings, 1 reply; 66+ messages in thread
From: Johannes Berg @ 2008-12-11 18:14 UTC (permalink / raw)
  To: Henning Rogge
  Cc: Henning Rogge, Luis R. Rodriguez, Luis Rodriguez,
	Marcel Holtmann, linux-wireless, nbd

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

On Thu, 2008-12-11 at 19:02 +0100, Henning Rogge wrote:

> Okay... I have included a casting to s8 into cfg.c so everyone is warned... 
> the original signal field in the sta_info struct is an int, but this structure 
> is used by the drivers so I don't want to touch it.

Right, not sure what happens when it's not in dBm anyway.

> > Can you also send me the corresponding iw patch?
> Have to write a modified one, I will post it later this evening I think.

Ok. I noticed a few more things, sorry:

> + * enum nl80211_rate_info - bitrate information
> + *
> + * These attribute types are used with %NL80211_STA_INFO_TXRATE
> + * when getting information about the bitrate of a station.
> + *
> + * @__NL80211_RATE_INFO_INVALID: attribute number 0 is reserved
> + * @NL80211_RATE_INFO_BITRATE: total bitrate (u16, 100kbit/s)
> + * @NL80211_RATE_INFO_MCS: mcs index for 802.11n (u8)
> + * @NL80211_RATE_INFO_40_MHZ_WIDTH: 40 Mhz dualchannel bitrate
> + * @NL80211_RATE_INFO_SHORT_GI: 400ns guard interval

This needs documentation for __...after_last and ..._max too, I think,
or kernel-doc will complain, and then I get email on the next daily git
update and complain ;)

Other than that,

Acked-by: Johannes Berg <johannes@sipsolutions.net>

so feel free to add that into the patch when you resend.

johannes

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

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

* Re: [Patch] nl80211: Add signal strength and bandwith to nl80211station info
  2008-12-11 18:14                                                                           ` Johannes Berg
@ 2008-12-11 18:22                                                                             ` Henning Rogge
  2008-12-11 18:28                                                                               ` Johannes Berg
  0 siblings, 1 reply; 66+ messages in thread
From: Henning Rogge @ 2008-12-11 18:22 UTC (permalink / raw)
  To: Johannes Berg
  Cc: Henning Rogge, Luis R. Rodriguez, Luis Rodriguez,
	Marcel Holtmann, linux-wireless, nbd

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

On Thursday 11 December 2008 19:14:47 you wrote:
> > Okay... I have included a casting to s8 into cfg.c so everyone is
> > warned... the original signal field in the sta_info struct is an int, but
> > this structure is used by the drivers so I don't want to touch it.
>
> Right, not sure what happens when it's not in dBm anyway.
>
> Ok. I noticed a few more things, sorry:
no problem... I want to get the bugs out of the patch, not to get it "in" as 
soon as possible.

> > + * enum nl80211_rate_info - bitrate information
> > + *
> > + * These attribute types are used with %NL80211_STA_INFO_TXRATE
> > + * when getting information about the bitrate of a station.
> > + *
> > + * @__NL80211_RATE_INFO_INVALID: attribute number 0 is reserved
> > + * @NL80211_RATE_INFO_BITRATE: total bitrate (u16, 100kbit/s)
> > + * @NL80211_RATE_INFO_MCS: mcs index for 802.11n (u8)
> > + * @NL80211_RATE_INFO_40_MHZ_WIDTH: 40 Mhz dualchannel bitrate
> > + * @NL80211_RATE_INFO_SHORT_GI: 400ns guard interval
>
> This needs documentation for __...after_last and ..._max too, I think,
> or kernel-doc will complain, and then I get email on the next daily git
> update and complain ;)
Is there a script to check for mistakes like this ? I used checkpatch.pl and 
it did not complain... 

> Other than that,
>
> Acked-by: Johannes Berg <johannes@sipsolutions.net>
>
> so feel free to add that into the patch when you resend.
I will... together with the iw patch.

Henning

[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 197 bytes --]

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

* Re: [Patch] nl80211: Add signal strength and bandwith to nl80211station info
  2008-12-11 18:22                                                                             ` Henning Rogge
@ 2008-12-11 18:28                                                                               ` Johannes Berg
  2008-12-11 20:10                                                                                 ` Henning Rogge
  2008-12-11 20:12                                                                                 ` Henning Rogge
  0 siblings, 2 replies; 66+ messages in thread
From: Johannes Berg @ 2008-12-11 18:28 UTC (permalink / raw)
  To: Henning Rogge
  Cc: Henning Rogge, Luis R. Rodriguez, Luis Rodriguez,
	Marcel Holtmann, linux-wireless, nbd

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

On Thu, 2008-12-11 at 19:22 +0100, Henning Rogge wrote:

> > This needs documentation for __...after_last and ..._max too, I think,
> > or kernel-doc will complain, and then I get email on the next daily git
> > update and complain ;)
> Is there a script to check for mistakes like this ? I used checkpatch.pl and 
> it did not complain... 

well, apply the patch and do

make htmldocs DOCBOOKS=mac80211.xml

Actually, hmm, I think, that won't help, because these files aren't
included yet. Heh.

johannes

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

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

* Re: [Patch] nl80211: Add signal strength and bandwith to nl80211station info
  2008-12-11 18:28                                                                               ` Johannes Berg
@ 2008-12-11 20:10                                                                                 ` Henning Rogge
  2008-12-11 20:24                                                                                   ` Johannes Berg
  2008-12-11 20:12                                                                                 ` Henning Rogge
  1 sibling, 1 reply; 66+ messages in thread
From: Henning Rogge @ 2008-12-11 20:10 UTC (permalink / raw)
  To: Johannes Berg
  Cc: Henning Rogge, Luis R. Rodriguez, Luis Rodriguez,
	Marcel Holtmann, linux-wireless, nbd


[-- Attachment #1.1: Type: text/plain, Size: 5470 bytes --]

I noticed the MAX/AFTER_LAST comments are missing for most nl80211 enums. ;)

But I get this output on my local (2 card) ad-hoc network:
# ./iw dev wlan0 station dump
Station 00:1b:fc:91:7d:d2 (on wlan0)
        inactive time:  52 ms
        rx bytes:       207220
        tx bytes:       1396
        signal:         -66 dBm
        tx bitrate:     18.0 MBit/s

Patch for iw attached (based on git tree an hour ago). Of course the 802.11n 
output part is only compile tested. Most of the patch is to put the new copy 
of nl80211.h into iw (why does iw carry a copy of this file ?)

Henning
------------
diff --git a/nl80211.h b/nl80211.h
index 04d4516..cc93e7a 100644
--- a/nl80211.h
+++ b/nl80211.h
@@ -425,6 +425,30 @@ enum nl80211_sta_flags {
 };
 
 /**
+ * enum nl80211_rate_info - bitrate information
+ *
+ * These attribute types are used with %NL80211_STA_INFO_TXRATE
+ * when getting information about the bitrate of a station.
+ *
+ * @__NL80211_RATE_INFO_INVALID: attribute number 0 is reserved
+ * @NL80211_RATE_INFO_BITRATE: total bitrate (u16, 100kbit/s)
+ * @NL80211_RATE_INFO_MCS: mcs index for 802.11n (u8)
+ * @NL80211_RATE_INFO_40_MHZ_WIDTH: 40 Mhz dualchannel bitrate
+ * @NL80211_RATE_INFO_SHORT_GI: 400ns guard interval
+ */
+enum nl80211_rate_info {
+	__NL80211_RATE_INFO_INVALID,
+	NL80211_RATE_INFO_BITRATE,
+	NL80211_RATE_INFO_MCS,
+	NL80211_RATE_INFO_40_MHZ_WIDTH,
+	NL80211_RATE_INFO_SHORT_GI,
+
+	/* keep last */
+	__NL80211_RATE_INFO_AFTER_LAST,
+	NL80211_RATE_INFO_MAX = __NL80211_RATE_INFO_AFTER_LAST - 1
+};
+
+/**
  * enum nl80211_sta_info - station information
  *
  * These attribute types are used with %NL80211_ATTR_STA_INFO
@@ -436,6 +460,9 @@ enum nl80211_sta_flags {
  * @NL80211_STA_INFO_TX_BYTES: total transmitted bytes (u32, to this station)
  * @__NL80211_STA_INFO_AFTER_LAST: internal
  * @NL80211_STA_INFO_MAX: highest possible station info attribute
+ * @NL80211_STA_INFO_SIGNAL: signal strength of last received PPDU (u8, dBm)
+ * @NL80211_STA_INFO_TX_BITRATE: current unicast tx rate, nested attribute
+ * 	containing info as possible, see &enum nl80211_sta_info_txrate.
  */
 enum nl80211_sta_info {
 	__NL80211_STA_INFO_INVALID,
@@ -445,6 +472,8 @@ enum nl80211_sta_info {
 	NL80211_STA_INFO_LLID,
 	NL80211_STA_INFO_PLID,
 	NL80211_STA_INFO_PLINK_STATE,
+	NL80211_STA_INFO_SIGNAL,
+	NL80211_STA_INFO_TX_BITRATE,
 
 	/* keep last */
 	__NL80211_STA_INFO_AFTER_LAST,
diff --git a/station.c b/station.c
index 6503574..cf13f61 100644
--- a/station.c
+++ b/station.c
@@ -27,22 +27,31 @@ enum plink_actions {
 	PLINK_ACTION_BLOCK,
 };
 
-
 static int print_sta_handler(struct nl_msg *msg, void *arg)
 {
 	struct nlattr *tb[NL80211_ATTR_MAX + 1];
 	struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
 	struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
+	struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
 	char mac_addr[20], state_name[10], dev[20];
 	static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
 		[NL80211_STA_INFO_INACTIVE_TIME] = { .type = NLA_U32 },
 		[NL80211_STA_INFO_RX_BYTES] = { .type = NLA_U32 },
 		[NL80211_STA_INFO_TX_BYTES] = { .type = NLA_U32 },
+		[NL80211_STA_INFO_SIGNAL] = { .type = NLA_U8 },
+		[NL80211_STA_INFO_TX_BITRATE] = { .type = NLA_NESTED },
 		[NL80211_STA_INFO_LLID] = { .type = NLA_U16 },
 		[NL80211_STA_INFO_PLID] = { .type = NLA_U16 },
 		[NL80211_STA_INFO_PLINK_STATE] = { .type = NLA_U8 },
 	};
 
+	static struct nla_policy rate_policy[NL80211_RATE_INFO_MAX + 1] = {
+		[NL80211_RATE_INFO_BITRATE] = { .type = NLA_U16 },
+		[NL80211_RATE_INFO_MCS] = { .type = NLA_U8 },
+		[NL80211_RATE_INFO_40_MHZ_WIDTH] = { .type = NLA_FLAG },
+		[NL80211_RATE_INFO_SHORT_GI] = { .type = NLA_FLAG },
+	};
+
 	nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
 		  genlmsg_attrlen(gnlh, 0), NULL);
 
@@ -62,7 +71,7 @@ static int print_sta_handler(struct nl_msg *msg, void *arg)
 		fprintf(stderr, "failed to parse nested attributes!");
 		return NL_SKIP;
 	}
-
+	
 	mac_addr_n2a(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
 	if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
 	printf("Station %s (on %s)", mac_addr, dev);
@@ -76,6 +85,33 @@ static int print_sta_handler(struct nl_msg *msg, void *arg)
 	if (sinfo[NL80211_STA_INFO_TX_BYTES])
 		printf("\n\ttx bytes:\t%d",
 			nla_get_u32(sinfo[NL80211_STA_INFO_TX_BYTES]));
+	if (sinfo[NL80211_STA_INFO_SIGNAL])
+		printf("\n\tsignal:  \t%d dBm",
+			(int8_t)nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]));
+
+	if (sinfo[NL80211_STA_INFO_TX_BITRATE]) {
+		if (nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX,
+				sinfo[NL80211_STA_INFO_TX_BITRATE],
+				rate_policy)) {
+			fprintf(stderr, "failed to parse nested rate attributes!");
+		} else {
+			printf("\n\ttx bitrate:\t");
+			if (rinfo[NL80211_RATE_INFO_BITRATE]) {
+				int rate = nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
+				printf("%d.%d MBit/s", rate / 10, rate % 10);
+			}
+			else
+				printf("?");
+
+			if (rinfo[NL80211_RATE_INFO_MCS])
+				printf(" msc:%d",
+					nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]));
+			if (rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
+				printf(" 40Mhz");
+			if (rinfo[NL80211_RATE_INFO_SHORT_GI])
+				printf(" short-guard-interval");
+		}
+	}
 	if (sinfo[NL80211_STA_INFO_LLID])
 		printf("\n\tmesh llid:\t%d",
 			nla_get_u16(sinfo[NL80211_STA_INFO_LLID]));


[-- Attachment #1.2: iw.patch --]
[-- Type: text/x-patch, Size: 4847 bytes --]

diff --git a/nl80211.h b/nl80211.h
index 04d4516..cc93e7a 100644
--- a/nl80211.h
+++ b/nl80211.h
@@ -425,6 +425,30 @@ enum nl80211_sta_flags {
 };
 
 /**
+ * enum nl80211_rate_info - bitrate information
+ *
+ * These attribute types are used with %NL80211_STA_INFO_TXRATE
+ * when getting information about the bitrate of a station.
+ *
+ * @__NL80211_RATE_INFO_INVALID: attribute number 0 is reserved
+ * @NL80211_RATE_INFO_BITRATE: total bitrate (u16, 100kbit/s)
+ * @NL80211_RATE_INFO_MCS: mcs index for 802.11n (u8)
+ * @NL80211_RATE_INFO_40_MHZ_WIDTH: 40 Mhz dualchannel bitrate
+ * @NL80211_RATE_INFO_SHORT_GI: 400ns guard interval
+ */
+enum nl80211_rate_info {
+	__NL80211_RATE_INFO_INVALID,
+	NL80211_RATE_INFO_BITRATE,
+	NL80211_RATE_INFO_MCS,
+	NL80211_RATE_INFO_40_MHZ_WIDTH,
+	NL80211_RATE_INFO_SHORT_GI,
+
+	/* keep last */
+	__NL80211_RATE_INFO_AFTER_LAST,
+	NL80211_RATE_INFO_MAX = __NL80211_RATE_INFO_AFTER_LAST - 1
+};
+
+/**
  * enum nl80211_sta_info - station information
  *
  * These attribute types are used with %NL80211_ATTR_STA_INFO
@@ -436,6 +460,9 @@ enum nl80211_sta_flags {
  * @NL80211_STA_INFO_TX_BYTES: total transmitted bytes (u32, to this station)
  * @__NL80211_STA_INFO_AFTER_LAST: internal
  * @NL80211_STA_INFO_MAX: highest possible station info attribute
+ * @NL80211_STA_INFO_SIGNAL: signal strength of last received PPDU (u8, dBm)
+ * @NL80211_STA_INFO_TX_BITRATE: current unicast tx rate, nested attribute
+ * 	containing info as possible, see &enum nl80211_sta_info_txrate.
  */
 enum nl80211_sta_info {
 	__NL80211_STA_INFO_INVALID,
@@ -445,6 +472,8 @@ enum nl80211_sta_info {
 	NL80211_STA_INFO_LLID,
 	NL80211_STA_INFO_PLID,
 	NL80211_STA_INFO_PLINK_STATE,
+	NL80211_STA_INFO_SIGNAL,
+	NL80211_STA_INFO_TX_BITRATE,
 
 	/* keep last */
 	__NL80211_STA_INFO_AFTER_LAST,
diff --git a/station.c b/station.c
index 6503574..cf13f61 100644
--- a/station.c
+++ b/station.c
@@ -27,22 +27,31 @@ enum plink_actions {
 	PLINK_ACTION_BLOCK,
 };
 
-
 static int print_sta_handler(struct nl_msg *msg, void *arg)
 {
 	struct nlattr *tb[NL80211_ATTR_MAX + 1];
 	struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
 	struct nlattr *sinfo[NL80211_STA_INFO_MAX + 1];
+	struct nlattr *rinfo[NL80211_RATE_INFO_MAX + 1];
 	char mac_addr[20], state_name[10], dev[20];
 	static struct nla_policy stats_policy[NL80211_STA_INFO_MAX + 1] = {
 		[NL80211_STA_INFO_INACTIVE_TIME] = { .type = NLA_U32 },
 		[NL80211_STA_INFO_RX_BYTES] = { .type = NLA_U32 },
 		[NL80211_STA_INFO_TX_BYTES] = { .type = NLA_U32 },
+		[NL80211_STA_INFO_SIGNAL] = { .type = NLA_U8 },
+		[NL80211_STA_INFO_TX_BITRATE] = { .type = NLA_NESTED },
 		[NL80211_STA_INFO_LLID] = { .type = NLA_U16 },
 		[NL80211_STA_INFO_PLID] = { .type = NLA_U16 },
 		[NL80211_STA_INFO_PLINK_STATE] = { .type = NLA_U8 },
 	};
 
+	static struct nla_policy rate_policy[NL80211_RATE_INFO_MAX + 1] = {
+		[NL80211_RATE_INFO_BITRATE] = { .type = NLA_U16 },
+		[NL80211_RATE_INFO_MCS] = { .type = NLA_U8 },
+		[NL80211_RATE_INFO_40_MHZ_WIDTH] = { .type = NLA_FLAG },
+		[NL80211_RATE_INFO_SHORT_GI] = { .type = NLA_FLAG },
+	};
+
 	nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
 		  genlmsg_attrlen(gnlh, 0), NULL);
 
@@ -62,7 +71,7 @@ static int print_sta_handler(struct nl_msg *msg, void *arg)
 		fprintf(stderr, "failed to parse nested attributes!");
 		return NL_SKIP;
 	}
-
+	
 	mac_addr_n2a(mac_addr, nla_data(tb[NL80211_ATTR_MAC]));
 	if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
 	printf("Station %s (on %s)", mac_addr, dev);
@@ -76,6 +85,33 @@ static int print_sta_handler(struct nl_msg *msg, void *arg)
 	if (sinfo[NL80211_STA_INFO_TX_BYTES])
 		printf("\n\ttx bytes:\t%d",
 			nla_get_u32(sinfo[NL80211_STA_INFO_TX_BYTES]));
+	if (sinfo[NL80211_STA_INFO_SIGNAL])
+		printf("\n\tsignal:  \t%d dBm",
+			(int8_t)nla_get_u8(sinfo[NL80211_STA_INFO_SIGNAL]));
+
+	if (sinfo[NL80211_STA_INFO_TX_BITRATE]) {
+		if (nla_parse_nested(rinfo, NL80211_RATE_INFO_MAX,
+				sinfo[NL80211_STA_INFO_TX_BITRATE],
+				rate_policy)) {
+			fprintf(stderr, "failed to parse nested rate attributes!");
+		} else {
+			printf("\n\ttx bitrate:\t");
+			if (rinfo[NL80211_RATE_INFO_BITRATE]) {
+				int rate = nla_get_u16(rinfo[NL80211_RATE_INFO_BITRATE]);
+				printf("%d.%d MBit/s", rate / 10, rate % 10);
+			}
+			else
+				printf("?");
+
+			if (rinfo[NL80211_RATE_INFO_MCS])
+				printf(" msc:%d",
+					nla_get_u8(rinfo[NL80211_RATE_INFO_MCS]));
+			if (rinfo[NL80211_RATE_INFO_40_MHZ_WIDTH])
+				printf(" 40Mhz");
+			if (rinfo[NL80211_RATE_INFO_SHORT_GI])
+				printf(" short-guard-interval");
+		}
+	}
 	if (sinfo[NL80211_STA_INFO_LLID])
 		printf("\n\tmesh llid:\t%d",
 			nla_get_u16(sinfo[NL80211_STA_INFO_LLID]));

[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 197 bytes --]

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

* Re: [Patch] nl80211: Add signal strength and bandwith to nl80211station info
  2008-12-11 18:28                                                                               ` Johannes Berg
  2008-12-11 20:10                                                                                 ` Henning Rogge
@ 2008-12-11 20:12                                                                                 ` Henning Rogge
  2008-12-11 20:23                                                                                   ` Johannes Berg
  1 sibling, 1 reply; 66+ messages in thread
From: Henning Rogge @ 2008-12-11 20:12 UTC (permalink / raw)
  To: Johannes Berg
  Cc: Henning Rogge, Luis R. Rodriguez, Luis Rodriguez,
	Marcel Holtmann, linux-wireless, nbd


[-- Attachment #1.1: Type: text/plain, Size: 8415 bytes --]

This patch adds signal strength and transmission bitrate
to the station_info of nl80211.

Signed-off-by: Henning Rogge <rogge@fgan.de>
Acked-by: Johannes Berg <johannes@sipsolutions.net>
---
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index 04d4516..7501acf 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -425,6 +425,32 @@ enum nl80211_sta_flags {
 };
 
 /**
+ * enum nl80211_rate_info - bitrate information
+ *
+ * These attribute types are used with %NL80211_STA_INFO_TXRATE
+ * when getting information about the bitrate of a station.
+ *
+ * @__NL80211_RATE_INFO_INVALID: attribute number 0 is reserved
+ * @NL80211_RATE_INFO_BITRATE: total bitrate (u16, 100kbit/s)
+ * @NL80211_RATE_INFO_MCS: mcs index for 802.11n (u8)
+ * @NL80211_RATE_INFO_40_MHZ_WIDTH: 40 Mhz dualchannel bitrate
+ * @NL80211_RATE_INFO_SHORT_GI: 400ns guard interval
+ * @NL80211_RATE_INFO_MAX: highest rate_info number currently defined
+ * @__NL80211_RATE_INFO_AFTER_LAST: internal use
+ */
+enum nl80211_rate_info {
+	__NL80211_RATE_INFO_INVALID,
+	NL80211_RATE_INFO_BITRATE,
+	NL80211_RATE_INFO_MCS,
+	NL80211_RATE_INFO_40_MHZ_WIDTH,
+	NL80211_RATE_INFO_SHORT_GI,
+
+	/* keep last */
+	__NL80211_RATE_INFO_AFTER_LAST,
+	NL80211_RATE_INFO_MAX = __NL80211_RATE_INFO_AFTER_LAST - 1
+};
+
+/**
  * enum nl80211_sta_info - station information
  *
  * These attribute types are used with %NL80211_ATTR_STA_INFO
@@ -436,6 +462,9 @@ enum nl80211_sta_flags {
  * @NL80211_STA_INFO_TX_BYTES: total transmitted bytes (u32, to this station)
  * @__NL80211_STA_INFO_AFTER_LAST: internal
  * @NL80211_STA_INFO_MAX: highest possible station info attribute
+ * @NL80211_STA_INFO_SIGNAL: signal strength of last received PPDU (u8, dBm)
+ * @NL80211_STA_INFO_TX_BITRATE: current unicast tx rate, nested attribute
+ * 	containing info as possible, see &enum nl80211_sta_info_txrate.
  */
 enum nl80211_sta_info {
 	__NL80211_STA_INFO_INVALID,
@@ -445,6 +474,8 @@ enum nl80211_sta_info {
 	NL80211_STA_INFO_LLID,
 	NL80211_STA_INFO_PLID,
 	NL80211_STA_INFO_PLINK_STATE,
+	NL80211_STA_INFO_SIGNAL,
+	NL80211_STA_INFO_TX_BITRATE,
 
 	/* keep last */
 	__NL80211_STA_INFO_AFTER_LAST,
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index a0c0bf1..65e03ac 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -169,6 +169,9 @@ struct station_parameters {
  * @STATION_INFO_LLID: @llid filled
  * @STATION_INFO_PLID: @plid filled
  * @STATION_INFO_PLINK_STATE: @plink_state filled
+ * @STATION_INFO_SIGNAL: @signal filled
+ * @STATION_INFO_TX_BITRATE: @tx_bitrate fields are filled
+ *  (tx_bitrate, tx_bitrate_flags and tx_bitrate_mcs)
  */
 enum station_info_flags {
 	STATION_INFO_INACTIVE_TIME	= 1<<0,
@@ -177,6 +180,39 @@ enum station_info_flags {
 	STATION_INFO_LLID		= 1<<3,
 	STATION_INFO_PLID		= 1<<4,
 	STATION_INFO_PLINK_STATE	= 1<<5,
+	STATION_INFO_SIGNAL		= 1<<6,
+	STATION_INFO_TX_BITRATE		= 1<<7,
+};
+
+/**
+ * enum station_info_rate_flags - bitrate info flags
+ *
+ * Used by the driver to indicate the specific rate transmission
+ * type for 802.11n transmissions.
+ *
+ * @RATE_INFO_FLAGS_MCS: @tx_bitrate_mcs filled
+ * @RATE_INFO_FLAGS_40_MHZ_WIDTH: 40 Mhz width transmission
+ * @RATE_INFO_FLAGS_SHORT_GI: 400ns guard interval
+ */
+enum rate_info_flags {
+	RATE_INFO_FLAGS_MCS		= 1<<0,
+	RATE_INFO_FLAGS_40_MHZ_WIDTH	= 1<<1,
+	RATE_INFO_FLAGS_SHORT_GI	= 1<<2,
+};
+
+/**
+ * struct rate_info - bitrate information
+ *
+ * Information about a receiving or transmitting bitrate
+ *
+ * @flags: bitflag of flags from &enum rate_info_flags
+ * @mcs: mcs index if struct describes a 802.11n bitrate
+ * @legacy: bitrate in 100kbit/s for 802.11abg
+ */
+struct rate_info {
+	u8 flags;
+	u8 mcs;
+	u16 legacy;
 };
 
 /**
@@ -191,6 +227,8 @@ enum station_info_flags {
  * @llid: mesh local link id
  * @plid: mesh peer link id
  * @plink_state: mesh peer link state
+ * @signal: signal strength of last received packet in dBm
+ * @txrate: current unicast bitrate to this station
  */
 struct station_info {
 	u32 filled;
@@ -200,6 +238,8 @@ struct station_info {
 	u16 llid;
 	u16 plid;
 	u8 plink_state;
+	s8 signal;
+	struct rate_info txrate;
 };
 
 /**
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 7912eb1..23b5eea 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -310,12 +310,35 @@ static void sta_set_sinfo(struct sta_info *sta, struct 
station_info *sinfo)
 
 	sinfo->filled = STATION_INFO_INACTIVE_TIME |
 			STATION_INFO_RX_BYTES |
-			STATION_INFO_TX_BYTES;
+			STATION_INFO_TX_BYTES |
+			STATION_INFO_TX_BITRATE;
 
 	sinfo->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx);
 	sinfo->rx_bytes = sta->rx_bytes;
 	sinfo->tx_bytes = sta->tx_bytes;
 
+	if (sta->local->hw.flags & IEEE80211_HW_SIGNAL_DBM) {
+		sinfo->filled |= STATION_INFO_SIGNAL;
+		sinfo->signal = (s8)sta->last_signal;
+	}
+
+	sinfo->txrate.flags = 0;
+	if (sta->last_tx_rate.flags & IEEE80211_TX_RC_MCS)
+		sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
+	if (sta->last_tx_rate.flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
+		sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
+	if (sta->last_tx_rate.flags & IEEE80211_TX_RC_SHORT_GI)
+		sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
+
+	if (!(sta->last_tx_rate.flags & IEEE80211_TX_RC_MCS)) {
+		struct ieee80211_supported_band *sband;
+		sband = sta->local->hw.wiphy->bands[
+				sta->local->hw.conf.channel->band];
+		sinfo->txrate.legacy =
+			sband->bitrates[sta->last_tx_rate.idx].bitrate;
+	} else
+		sinfo->txrate.mcs = sta->last_tx_rate.idx;
+
 	if (ieee80211_vif_is_mesh(&sdata->vif)) {
 #ifdef CONFIG_MAC80211_MESH
 		sinfo->filled |= STATION_INFO_LLID |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 4335f76..93c9b98 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -1091,12 +1091,46 @@ static int parse_station_flags(struct nlattr *nla, u32 
*staflags)
 	return 0;
 }
 
+static u16 nl80211_calculate_bitrate(struct rate_info *rate)
+{
+	int modulation, streams, bitrate;
+
+	if (!(rate->flags & RATE_INFO_FLAGS_MCS))
+		return rate->legacy;
+
+	/* the formula below does only work for MCS values smaller than 32 */
+	if (rate->mcs >= 32)
+		return 0;
+
+	modulation = rate->mcs & 7;
+	streams = (rate->mcs >> 3) + 1;
+
+	bitrate = (rate->flags & RATE_INFO_FLAGS_40_MHZ_WIDTH) ?
+			13500000 : 6500000;
+
+	if (modulation < 4)
+		bitrate *= (modulation + 1);
+	else if (modulation == 4)
+		bitrate *= (modulation + 2);
+	else
+		bitrate *= (modulation + 3);
+
+	bitrate *= streams;
+
+	if (rate->flags & RATE_INFO_FLAGS_SHORT_GI)
+		bitrate = (bitrate / 9) * 10;
+
+	/* do NOT round down here */
+	return (bitrate + 50000) / 100000;
+}
+
 static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
 				int flags, struct net_device *dev,
 				u8 *mac_addr, struct station_info *sinfo)
 {
 	void *hdr;
-	struct nlattr *sinfoattr;
+	struct nlattr *sinfoattr, *txrate;
+	u16 bitrate;
 
 	hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_STATION);
 	if (!hdr)
@@ -1126,7 +1160,29 @@ static int nl80211_send_station(struct sk_buff *msg, 
u32 pid, u32 seq,
 	if (sinfo->filled & STATION_INFO_PLINK_STATE)
 		NLA_PUT_U8(msg, NL80211_STA_INFO_PLINK_STATE,
 			    sinfo->plink_state);
+	if (sinfo->filled & STATION_INFO_SIGNAL)
+		NLA_PUT_U8(msg, NL80211_STA_INFO_SIGNAL,
+			   sinfo->signal);
+	if (sinfo->filled & STATION_INFO_TX_BITRATE) {
+		txrate = nla_nest_start(msg, NL80211_STA_INFO_TX_BITRATE);
+		if (!txrate)
+			goto nla_put_failure;
+
+		/* nl80211_calculate_bitrate will return 0 for mcs >= 32 */
+		bitrate = nl80211_calculate_bitrate(&sinfo->txrate);
+		if (bitrate > 0)
+			NLA_PUT_U16(msg, NL80211_RATE_INFO_BITRATE, bitrate);
 
+		if (sinfo->txrate.flags & RATE_INFO_FLAGS_MCS)
+			NLA_PUT_U8(msg, NL80211_RATE_INFO_MCS,
+				    sinfo->txrate.mcs);
+		if (sinfo->txrate.flags & RATE_INFO_FLAGS_40_MHZ_WIDTH)
+			NLA_PUT_FLAG(msg, NL80211_RATE_INFO_40_MHZ_WIDTH);
+		if (sinfo->txrate.flags & RATE_INFO_FLAGS_SHORT_GI)
+			NLA_PUT_FLAG(msg, NL80211_RATE_INFO_SHORT_GI);
+
+		nla_nest_end(msg, txrate);
+	}
 	nla_nest_end(msg, sinfoattr);
 
 	return genlmsg_end(msg, hdr);


[-- Attachment #1.2: nl80211ext_v14.patch --]
[-- Type: text/x-patch, Size: 8407 bytes --]

This patch adds signal strength and transmission bitrate
to the station_info of nl80211.

Signed-off-by: Henning Rogge <rogge@fgan.de>
Acked-by: Johannes Berg <johannes@sipsolutions.net>
---
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index 04d4516..7501acf 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -425,6 +425,32 @@ enum nl80211_sta_flags {
 };
 
 /**
+ * enum nl80211_rate_info - bitrate information
+ *
+ * These attribute types are used with %NL80211_STA_INFO_TXRATE
+ * when getting information about the bitrate of a station.
+ *
+ * @__NL80211_RATE_INFO_INVALID: attribute number 0 is reserved
+ * @NL80211_RATE_INFO_BITRATE: total bitrate (u16, 100kbit/s)
+ * @NL80211_RATE_INFO_MCS: mcs index for 802.11n (u8)
+ * @NL80211_RATE_INFO_40_MHZ_WIDTH: 40 Mhz dualchannel bitrate
+ * @NL80211_RATE_INFO_SHORT_GI: 400ns guard interval
+ * @NL80211_RATE_INFO_MAX: highest rate_info number currently defined
+ * @__NL80211_RATE_INFO_AFTER_LAST: internal use
+ */
+enum nl80211_rate_info {
+	__NL80211_RATE_INFO_INVALID,
+	NL80211_RATE_INFO_BITRATE,
+	NL80211_RATE_INFO_MCS,
+	NL80211_RATE_INFO_40_MHZ_WIDTH,
+	NL80211_RATE_INFO_SHORT_GI,
+
+	/* keep last */
+	__NL80211_RATE_INFO_AFTER_LAST,
+	NL80211_RATE_INFO_MAX = __NL80211_RATE_INFO_AFTER_LAST - 1
+};
+
+/**
  * enum nl80211_sta_info - station information
  *
  * These attribute types are used with %NL80211_ATTR_STA_INFO
@@ -436,6 +462,9 @@ enum nl80211_sta_flags {
  * @NL80211_STA_INFO_TX_BYTES: total transmitted bytes (u32, to this station)
  * @__NL80211_STA_INFO_AFTER_LAST: internal
  * @NL80211_STA_INFO_MAX: highest possible station info attribute
+ * @NL80211_STA_INFO_SIGNAL: signal strength of last received PPDU (u8, dBm)
+ * @NL80211_STA_INFO_TX_BITRATE: current unicast tx rate, nested attribute
+ * 	containing info as possible, see &enum nl80211_sta_info_txrate.
  */
 enum nl80211_sta_info {
 	__NL80211_STA_INFO_INVALID,
@@ -445,6 +474,8 @@ enum nl80211_sta_info {
 	NL80211_STA_INFO_LLID,
 	NL80211_STA_INFO_PLID,
 	NL80211_STA_INFO_PLINK_STATE,
+	NL80211_STA_INFO_SIGNAL,
+	NL80211_STA_INFO_TX_BITRATE,
 
 	/* keep last */
 	__NL80211_STA_INFO_AFTER_LAST,
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index a0c0bf1..65e03ac 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -169,6 +169,9 @@ struct station_parameters {
  * @STATION_INFO_LLID: @llid filled
  * @STATION_INFO_PLID: @plid filled
  * @STATION_INFO_PLINK_STATE: @plink_state filled
+ * @STATION_INFO_SIGNAL: @signal filled
+ * @STATION_INFO_TX_BITRATE: @tx_bitrate fields are filled
+ *  (tx_bitrate, tx_bitrate_flags and tx_bitrate_mcs)
  */
 enum station_info_flags {
 	STATION_INFO_INACTIVE_TIME	= 1<<0,
@@ -177,6 +180,39 @@ enum station_info_flags {
 	STATION_INFO_LLID		= 1<<3,
 	STATION_INFO_PLID		= 1<<4,
 	STATION_INFO_PLINK_STATE	= 1<<5,
+	STATION_INFO_SIGNAL		= 1<<6,
+	STATION_INFO_TX_BITRATE		= 1<<7,
+};
+
+/**
+ * enum station_info_rate_flags - bitrate info flags
+ *
+ * Used by the driver to indicate the specific rate transmission
+ * type for 802.11n transmissions.
+ *
+ * @RATE_INFO_FLAGS_MCS: @tx_bitrate_mcs filled
+ * @RATE_INFO_FLAGS_40_MHZ_WIDTH: 40 Mhz width transmission
+ * @RATE_INFO_FLAGS_SHORT_GI: 400ns guard interval
+ */
+enum rate_info_flags {
+	RATE_INFO_FLAGS_MCS		= 1<<0,
+	RATE_INFO_FLAGS_40_MHZ_WIDTH	= 1<<1,
+	RATE_INFO_FLAGS_SHORT_GI	= 1<<2,
+};
+
+/**
+ * struct rate_info - bitrate information
+ *
+ * Information about a receiving or transmitting bitrate
+ *
+ * @flags: bitflag of flags from &enum rate_info_flags
+ * @mcs: mcs index if struct describes a 802.11n bitrate
+ * @legacy: bitrate in 100kbit/s for 802.11abg
+ */
+struct rate_info {
+	u8 flags;
+	u8 mcs;
+	u16 legacy;
 };
 
 /**
@@ -191,6 +227,8 @@ enum station_info_flags {
  * @llid: mesh local link id
  * @plid: mesh peer link id
  * @plink_state: mesh peer link state
+ * @signal: signal strength of last received packet in dBm
+ * @txrate: current unicast bitrate to this station
  */
 struct station_info {
 	u32 filled;
@@ -200,6 +238,8 @@ struct station_info {
 	u16 llid;
 	u16 plid;
 	u8 plink_state;
+	s8 signal;
+	struct rate_info txrate;
 };
 
 /**
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 7912eb1..23b5eea 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -310,12 +310,35 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
 
 	sinfo->filled = STATION_INFO_INACTIVE_TIME |
 			STATION_INFO_RX_BYTES |
-			STATION_INFO_TX_BYTES;
+			STATION_INFO_TX_BYTES |
+			STATION_INFO_TX_BITRATE;
 
 	sinfo->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx);
 	sinfo->rx_bytes = sta->rx_bytes;
 	sinfo->tx_bytes = sta->tx_bytes;
 
+	if (sta->local->hw.flags & IEEE80211_HW_SIGNAL_DBM) {
+		sinfo->filled |= STATION_INFO_SIGNAL;
+		sinfo->signal = (s8)sta->last_signal;
+	}
+
+	sinfo->txrate.flags = 0;
+	if (sta->last_tx_rate.flags & IEEE80211_TX_RC_MCS)
+		sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
+	if (sta->last_tx_rate.flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
+		sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
+	if (sta->last_tx_rate.flags & IEEE80211_TX_RC_SHORT_GI)
+		sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
+
+	if (!(sta->last_tx_rate.flags & IEEE80211_TX_RC_MCS)) {
+		struct ieee80211_supported_band *sband;
+		sband = sta->local->hw.wiphy->bands[
+				sta->local->hw.conf.channel->band];
+		sinfo->txrate.legacy =
+			sband->bitrates[sta->last_tx_rate.idx].bitrate;
+	} else
+		sinfo->txrate.mcs = sta->last_tx_rate.idx;
+
 	if (ieee80211_vif_is_mesh(&sdata->vif)) {
 #ifdef CONFIG_MAC80211_MESH
 		sinfo->filled |= STATION_INFO_LLID |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 4335f76..93c9b98 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -1091,12 +1091,46 @@ static int parse_station_flags(struct nlattr *nla, u32 *staflags)
 	return 0;
 }
 
+static u16 nl80211_calculate_bitrate(struct rate_info *rate)
+{
+	int modulation, streams, bitrate;
+
+	if (!(rate->flags & RATE_INFO_FLAGS_MCS))
+		return rate->legacy;
+
+	/* the formula below does only work for MCS values smaller than 32 */
+	if (rate->mcs >= 32)
+		return 0;
+
+	modulation = rate->mcs & 7;
+	streams = (rate->mcs >> 3) + 1;
+
+	bitrate = (rate->flags & RATE_INFO_FLAGS_40_MHZ_WIDTH) ?
+			13500000 : 6500000;
+
+	if (modulation < 4)
+		bitrate *= (modulation + 1);
+	else if (modulation == 4)
+		bitrate *= (modulation + 2);
+	else
+		bitrate *= (modulation + 3);
+
+	bitrate *= streams;
+
+	if (rate->flags & RATE_INFO_FLAGS_SHORT_GI)
+		bitrate = (bitrate / 9) * 10;
+
+	/* do NOT round down here */
+	return (bitrate + 50000) / 100000;
+}
+
 static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
 				int flags, struct net_device *dev,
 				u8 *mac_addr, struct station_info *sinfo)
 {
 	void *hdr;
-	struct nlattr *sinfoattr;
+	struct nlattr *sinfoattr, *txrate;
+	u16 bitrate;
 
 	hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_STATION);
 	if (!hdr)
@@ -1126,7 +1160,29 @@ static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
 	if (sinfo->filled & STATION_INFO_PLINK_STATE)
 		NLA_PUT_U8(msg, NL80211_STA_INFO_PLINK_STATE,
 			    sinfo->plink_state);
+	if (sinfo->filled & STATION_INFO_SIGNAL)
+		NLA_PUT_U8(msg, NL80211_STA_INFO_SIGNAL,
+			   sinfo->signal);
+	if (sinfo->filled & STATION_INFO_TX_BITRATE) {
+		txrate = nla_nest_start(msg, NL80211_STA_INFO_TX_BITRATE);
+		if (!txrate)
+			goto nla_put_failure;
+
+		/* nl80211_calculate_bitrate will return 0 for mcs >= 32 */
+		bitrate = nl80211_calculate_bitrate(&sinfo->txrate);
+		if (bitrate > 0)
+			NLA_PUT_U16(msg, NL80211_RATE_INFO_BITRATE, bitrate);
 
+		if (sinfo->txrate.flags & RATE_INFO_FLAGS_MCS)
+			NLA_PUT_U8(msg, NL80211_RATE_INFO_MCS,
+				    sinfo->txrate.mcs);
+		if (sinfo->txrate.flags & RATE_INFO_FLAGS_40_MHZ_WIDTH)
+			NLA_PUT_FLAG(msg, NL80211_RATE_INFO_40_MHZ_WIDTH);
+		if (sinfo->txrate.flags & RATE_INFO_FLAGS_SHORT_GI)
+			NLA_PUT_FLAG(msg, NL80211_RATE_INFO_SHORT_GI);
+
+		nla_nest_end(msg, txrate);
+	}
 	nla_nest_end(msg, sinfoattr);
 
 	return genlmsg_end(msg, hdr);

[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 197 bytes --]

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

* Re: [Patch] nl80211: Add signal strength and bandwith to nl80211station info
  2008-12-11 20:12                                                                                 ` Henning Rogge
@ 2008-12-11 20:23                                                                                   ` Johannes Berg
  0 siblings, 0 replies; 66+ messages in thread
From: Johannes Berg @ 2008-12-11 20:23 UTC (permalink / raw)
  To: Henning Rogge
  Cc: Henning Rogge, Luis R. Rodriguez, Luis Rodriguez,
	Marcel Holtmann, linux-wireless, nbd

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

On Thu, 2008-12-11 at 21:12 +0100, Henning Rogge wrote:
> This patch adds signal strength and transmission bitrate
> to the station_info of nl80211.
> 
> Signed-off-by: Henning Rogge <rogge@fgan.de>
> Acked-by: Johannes Berg <johannes@sipsolutions.net>

You should probably send this with just [PATCH v14] (no Re:), CC John
and not attach the file but make sure the inline version is ok (if
possible)

johannes

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

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

* Re: [Patch] nl80211: Add signal strength and bandwith to nl80211station info
  2008-12-11 20:10                                                                                 ` Henning Rogge
@ 2008-12-11 20:24                                                                                   ` Johannes Berg
  0 siblings, 0 replies; 66+ messages in thread
From: Johannes Berg @ 2008-12-11 20:24 UTC (permalink / raw)
  To: Henning Rogge
  Cc: Henning Rogge, Luis R. Rodriguez, Luis Rodriguez,
	Marcel Holtmann, linux-wireless, nbd

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

On Thu, 2008-12-11 at 21:10 +0100, Henning Rogge wrote:
> I noticed the MAX/AFTER_LAST comments are missing for most nl80211 enums. ;)

Hah

> But I get this output on my local (2 card) ad-hoc network:
> # ./iw dev wlan0 station dump
> Station 00:1b:fc:91:7d:d2 (on wlan0)
>         inactive time:  52 ms
>         rx bytes:       207220
>         tx bytes:       1396
>         signal:         -66 dBm
>         tx bitrate:     18.0 MBit/s
> 
> Patch for iw attached (based on git tree an hour ago). Of course the 802.11n 
> output part is only compile tested. Most of the patch is to put the new copy 
> of nl80211.h into iw (why does iw carry a copy of this file ?)

Because it's easier to build that way if you don't have a current tree.

I'll take the patch once the other one gets into the kernel tree.

johannes

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

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

end of thread, other threads:[~2008-12-11 20:24 UTC | newest]

Thread overview: 66+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-11-25 20:31 RFC Patch: Add signal strength to nl80211station info Henning Rogge
2008-11-25 20:47 ` Johannes Berg
2008-11-25 21:01   ` Henning Rogge
2008-11-26  5:21   ` Marcel Holtmann
2008-11-26  8:32     ` Johannes Berg
2008-11-26 16:17     ` Henning Rogge
2008-11-29 10:50     ` RFC Patch v2: " Henning Rogge
2008-12-01 11:17       ` Johannes Berg
2008-12-01 13:22         ` Henning Rogge
2008-12-01 17:39           ` Luis R. Rodriguez
2008-12-01 17:45             ` Luis R. Rodriguez
2008-12-01 17:53             ` Henning Rogge
2008-12-02 13:25             ` Henning Rogge
2008-12-02 20:29               ` Luis R. Rodriguez
2008-12-02 20:46                 ` Henning Rogge
2008-12-03  1:44                   ` Luis R. Rodriguez
2008-12-03 10:31                     ` Henning Rogge
2008-12-04  8:47                       ` Johannes Berg
2008-12-04  9:48                         ` Henning Rogge
2008-12-04 13:02                           ` Johannes Berg
2008-12-04 20:26                       ` Johannes Berg
2008-12-04 21:12                         ` Luis R. Rodriguez
2008-12-04 21:20                           ` Johannes Berg
2008-12-05  8:34                             ` Henning Rogge
2008-12-05  9:45                               ` Johannes Berg
2008-12-05  9:51                                 ` Henning Rogge
2008-12-05  9:54                                   ` Johannes Berg
2008-12-05 23:26                                     ` Henning Rogge
2008-12-06  9:15                                       ` Johannes Berg
2008-12-06 11:12                                         ` Henning Rogge
2008-12-06 14:10                                 ` Henning Rogge
2008-12-06 14:43                                   ` Henning Rogge
2008-12-06 14:51                                   ` Johannes Berg
2008-12-06 15:03                                     ` Henning Rogge
2008-12-06 15:46                                       ` Henning Rogge
2008-12-06 15:59                                         ` Johannes Berg
2008-12-06 16:08                                           ` Henning Rogge
2008-12-06 20:46                                           ` Luis R. Rodriguez
2008-12-07 17:32                                             ` Henning Rogge
2008-12-07 17:39                                               ` Johannes Berg
2008-12-07 18:17                                                 ` [PATCH 1/2] Add signal strength and bandwith " Henning Rogge
2008-12-08 19:43                                                   ` Johannes Berg
2008-12-09 19:50                                                     ` Henning Rogge
2008-12-09 21:16                                                       ` Johannes Berg
2008-12-10  6:53                                                         ` Henning Rogge
2008-12-10  9:05                                                           ` Johannes Berg
2008-12-10 17:40                                                             ` Henning Rogge
2008-12-10 20:45                                                               ` Johannes Berg
2008-12-10 20:58                                                                 ` Henning Rogge
2008-12-10 21:01                                                                   ` Johannes Berg
2008-12-11 17:07                                                                     ` [Patch] nl80211: " Henning Rogge
2008-12-11 17:24                                                                       ` Johannes Berg
2008-12-11 18:02                                                                         ` Henning Rogge
2008-12-11 18:14                                                                           ` Johannes Berg
2008-12-11 18:22                                                                             ` Henning Rogge
2008-12-11 18:28                                                                               ` Johannes Berg
2008-12-11 20:10                                                                                 ` Henning Rogge
2008-12-11 20:24                                                                                   ` Johannes Berg
2008-12-11 20:12                                                                                 ` Henning Rogge
2008-12-11 20:23                                                                                   ` Johannes Berg
2008-12-09 19:54                                                     ` [Patch 1/2 v2] " Henning Rogge
2008-12-09 19:58                                                     ` [Patch 2/2 " Henning Rogge
2008-12-09 21:19                                                       ` Johannes Berg
2008-12-07 18:19                                                 ` [PATCH 2/2] " Henning Rogge
2008-12-07 18:20                                                 ` [PATCH 0/2] " Henning Rogge
2008-12-06 15:48                                       ` RFC Patch v2: Add signal strength " Johannes Berg

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.