summaryrefslogtreecommitdiff
path: root/package/mac80211/patches/024-nl80211-get-sta.patch
diff options
context:
space:
mode:
Diffstat (limited to 'package/mac80211/patches/024-nl80211-get-sta.patch')
-rw-r--r--package/mac80211/patches/024-nl80211-get-sta.patch208
1 files changed, 208 insertions, 0 deletions
diff --git a/package/mac80211/patches/024-nl80211-get-sta.patch b/package/mac80211/patches/024-nl80211-get-sta.patch
new file mode 100644
index 0000000..198ad18
--- /dev/null
+++ b/package/mac80211/patches/024-nl80211-get-sta.patch
@@ -0,0 +1,208 @@
+Subject: cfg80211/nl80211: implement station attribute retrieval
+
+After a station is added to the kernel's structures, userspace
+has to be able to retrieve statistics about that station, especially
+whether the station was idle and how much bytes were transferred
+to and from it. This adds the necessary code to nl80211.
+
+Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
+
+---
+ include/linux/nl80211.h | 28 ++++++++++++++++
+ include/net/cfg80211.h | 35 ++++++++++++++++++++
+ net/wireless/nl80211.c | 82 +++++++++++++++++++++++++++++++++++++++++++++++-
+ 3 files changed, 144 insertions(+), 1 deletion(-)
+
+--- everything.orig/include/linux/nl80211.h 2007-11-08 17:15:15.961529840 +0100
++++ everything/include/linux/nl80211.h 2007-11-08 17:17:00.891547364 +0100
+@@ -157,6 +157,9 @@ enum nl80211_commands {
+ * restriction (at most %NL80211_MAX_SUPP_RATES).
+ * @NL80211_ATTR_STA_VLAN: interface index of VLAN interface to move station
+ * to, or the AP interface the station was originally added to to.
++ * @NL80211_ATTR_STA_STATS: statistics for a station, part of station info
++ * given for %NL80211_CMD_GET_STATION, nested attribute containing
++ * info as possible, see &enum nl80211_sta_stats.
+ *
+ * @NL80211_ATTR_MAX: highest attribute number currently defined
+ * @__NL80211_ATTR_AFTER_LAST: internal use
+@@ -190,6 +193,7 @@ enum nl80211_attrs {
+ NL80211_ATTR_STA_LISTEN_INTERVAL,
+ NL80211_ATTR_STA_SUPPORTED_RATES,
+ NL80211_ATTR_STA_VLAN,
++ NL80211_ATTR_STA_STATS,
+
+ /* add attributes here, update the policy in nl80211.c */
+
+@@ -252,4 +256,28 @@ enum nl80211_sta_flags {
+ NL80211_STA_FLAG_MAX = __NL80211_STA_FLAG_AFTER_LAST - 1
+ };
+
++/**
++ * enum nl80211_sta_stats - station statistics
++ *
++ * These attribute types are used with %NL80211_ATTR_STA_STATS
++ * when getting information about a station.
++ *
++ * @__NL80211_STA_STAT_INVALID: attribute number 0 is reserved
++ * @NL80211_STA_STAT_INACTIVE_TIME: time since last activity (u32, msecs)
++ * @NL80211_STA_STAT_RX_BYTES: total received bytes (u32, from this station)
++ * @NL80211_STA_STAT_TX_BYTES: total transmitted bytes (u32, to this station)
++ * @__NL80211_STA_STAT_AFTER_LAST: internal
++ * @NL80211_STA_STAT_MAX: highest possible station stats attribute
++ */
++enum nl80211_sta_stats {
++ __NL80211_STA_STAT_INVALID,
++ NL80211_STA_STAT_INACTIVE_TIME,
++ NL80211_STA_STAT_RX_BYTES,
++ NL80211_STA_STAT_TX_BYTES,
++
++ /* keep last */
++ __NL80211_STA_STAT_AFTER_LAST,
++ NL80211_STA_STAT_MAX = __NL80211_STA_STAT_AFTER_LAST - 1
++};
++
+ #endif /* __LINUX_NL80211_H */
+--- everything.orig/include/net/cfg80211.h 2007-11-08 17:15:15.971532444 +0100
++++ everything/include/net/cfg80211.h 2007-11-08 17:17:00.891547364 +0100
+@@ -130,6 +130,39 @@ struct station_parameters {
+ u8 supported_rates_len;
+ };
+
++/**
++ * enum station_stats_flags - station statistics flags
++ *
++ * Used by the driver to indicate which info in &struct station_stats
++ * it has filled in during get_station().
++ *
++ * @STATION_STAT_INACTIVE_TIME: @inactive_time filled
++ * @STATION_STAT_RX_BYTES: @rx_bytes filled
++ * @STATION_STAT_TX_BYTES: @tx_bytes filled
++ */
++enum station_stats_flags {
++ STATION_STAT_INACTIVE_TIME = 1<<0,
++ STATION_STAT_RX_BYTES = 1<<1,
++ STATION_STAT_TX_BYTES = 1<<2,
++};
++
++/**
++ * struct station_stats - station statistics
++ *
++ * Station information filled by driver for get_station().
++ *
++ * @filled: bitflag of flags from &enum station_stats_flags
++ * @inactive_time: time since last station activity (tx/rx) in milliseconds
++ * @rx_bytes: bytes received from this station
++ * @tx_bytes: bytes transmitted to this station
++ */
++struct station_stats {
++ u32 filled;
++ u32 inactive_time;
++ u32 rx_bytes;
++ u32 tx_bytes;
++};
++
+ /* from net/wireless.h */
+ struct wiphy;
+
+@@ -209,6 +242,8 @@ struct cfg80211_ops {
+ u8 *mac);
+ int (*change_station)(struct wiphy *wiphy, struct net_device *dev,
+ u8 *mac, struct station_parameters *params);
++ int (*get_station)(struct wiphy *wiphy, struct net_device *dev,
++ u8 *mac, struct station_stats *stats);
+ };
+
+ #endif /* __NET_CFG80211_H */
+--- everything.orig/net/wireless/nl80211.c 2007-11-08 17:15:15.981533909 +0100
++++ everything/net/wireless/nl80211.c 2007-11-08 17:17:00.901534235 +0100
+@@ -751,9 +751,89 @@ static int parse_station_flags(struct nl
+ return 0;
+ }
+
++static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
++ int flags, struct net_device *dev,
++ u8 *mac_addr, struct station_stats *stats)
++{
++ void *hdr;
++ struct nlattr *statsattr;
++
++ hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_STATION);
++ if (!hdr)
++ return -1;
++
++ NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex);
++ NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr);
++
++ statsattr = nla_nest_start(msg, NL80211_ATTR_STA_STATS);
++ if (!statsattr)
++ goto nla_put_failure;
++ if (stats->filled & STATION_STAT_INACTIVE_TIME)
++ NLA_PUT_U32(msg, NL80211_STA_STAT_INACTIVE_TIME,
++ stats->inactive_time);
++ if (stats->filled & STATION_STAT_RX_BYTES)
++ NLA_PUT_U32(msg, NL80211_STA_STAT_RX_BYTES,
++ stats->rx_bytes);
++ if (stats->filled & STATION_STAT_TX_BYTES)
++ NLA_PUT_U32(msg, NL80211_STA_STAT_TX_BYTES,
++ stats->tx_bytes);
++
++ nla_nest_end(msg, statsattr);
++
++ return genlmsg_end(msg, hdr);
++
++ nla_put_failure:
++ return genlmsg_cancel(msg, hdr);
++}
++
++
+ static int nl80211_get_station(struct sk_buff *skb, struct genl_info *info)
+ {
+- return -EOPNOTSUPP;
++ struct cfg80211_registered_device *drv;
++ int err;
++ struct net_device *dev;
++ struct station_stats stats;
++ struct sk_buff *msg;
++ u8 *mac_addr = NULL;
++
++ memset(&stats, 0, sizeof(stats));
++
++ if (!info->attrs[NL80211_ATTR_MAC])
++ return -EINVAL;
++
++ mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
++
++ err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
++ if (err)
++ return err;
++
++ if (!drv->ops->get_station) {
++ err = -EOPNOTSUPP;
++ goto out;
++ }
++
++ rtnl_lock();
++ err = drv->ops->get_station(&drv->wiphy, dev, mac_addr, &stats);
++ rtnl_unlock();
++
++ msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
++ if (!msg)
++ goto out;
++
++ if (nl80211_send_station(msg, info->snd_pid, info->snd_seq, 0,
++ dev, mac_addr, &stats) < 0)
++ goto out_free;
++
++ err = genlmsg_unicast(msg, info->snd_pid);
++ goto out;
++
++ out_free:
++ nlmsg_free(msg);
++
++ out:
++ cfg80211_put_dev(drv);
++ dev_put(dev);
++ return err;
+ }
+
+ /*