All of lore.kernel.org
 help / color / mirror / Atom feed
From: Henning Rogge <rogge@fgan.de>
To: "Luis R. Rodriguez" <lrodriguez@atheros.com>
Cc: Johannes Berg <johannes@sipsolutions.net>,
	Henning Rogge <hrogge@googlemail.com>,
	Marcel Holtmann <holtmann@linux.intel.com>,
	"linux-wireless" <linux-wireless@vger.kernel.org>,
	nbd@openwrt.org
Subject: RFC Patch v2: Add signal strength to nl80211station info
Date: Tue, 2 Dec 2008 14:25:36 +0100	[thread overview]
Message-ID: <200812021425.44488.rogge@fgan.de> (raw)
In-Reply-To: <20081201173948.GD5992@tesla>


[-- 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 --]

  parent reply	other threads:[~2008-12-02 13:25 UTC|newest]

Thread overview: 66+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
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 [this message]
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

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=200812021425.44488.rogge@fgan.de \
    --to=rogge@fgan.de \
    --cc=holtmann@linux.intel.com \
    --cc=hrogge@googlemail.com \
    --cc=johannes@sipsolutions.net \
    --cc=linux-wireless@vger.kernel.org \
    --cc=lrodriguez@atheros.com \
    --cc=nbd@openwrt.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.