1 Subject: cfg80211/nl80211: implement station attribute retrieval
3 After a station is added to the kernel's structures, userspace
4 has to be able to retrieve statistics about that station, especially
5 whether the station was idle and how much bytes were transferred
6 to and from it. This adds the necessary code to nl80211.
8 Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
11 include/linux/nl80211.h | 28 ++++++++++++++++
12 include/net/cfg80211.h | 35 ++++++++++++++++++++
13 net/wireless/nl80211.c | 82 +++++++++++++++++++++++++++++++++++++++++++++++-
14 3 files changed, 144 insertions(+), 1 deletion(-)
16 --- everything.orig/include/linux/nl80211.h 2007-11-08 17:15:15.961529840 +0100
17 +++ everything/include/linux/nl80211.h 2007-11-08 17:17:00.891547364 +0100
18 @@ -157,6 +157,9 @@ enum nl80211_commands {
19 * restriction (at most %NL80211_MAX_SUPP_RATES).
20 * @NL80211_ATTR_STA_VLAN: interface index of VLAN interface to move station
21 * to, or the AP interface the station was originally added to to.
22 + * @NL80211_ATTR_STA_STATS: statistics for a station, part of station info
23 + * given for %NL80211_CMD_GET_STATION, nested attribute containing
24 + * info as possible, see &enum nl80211_sta_stats.
26 * @NL80211_ATTR_MAX: highest attribute number currently defined
27 * @__NL80211_ATTR_AFTER_LAST: internal use
28 @@ -190,6 +193,7 @@ enum nl80211_attrs {
29 NL80211_ATTR_STA_LISTEN_INTERVAL,
30 NL80211_ATTR_STA_SUPPORTED_RATES,
31 NL80211_ATTR_STA_VLAN,
32 + NL80211_ATTR_STA_STATS,
34 /* add attributes here, update the policy in nl80211.c */
36 @@ -252,4 +256,28 @@ enum nl80211_sta_flags {
37 NL80211_STA_FLAG_MAX = __NL80211_STA_FLAG_AFTER_LAST - 1
41 + * enum nl80211_sta_stats - station statistics
43 + * These attribute types are used with %NL80211_ATTR_STA_STATS
44 + * when getting information about a station.
46 + * @__NL80211_STA_STAT_INVALID: attribute number 0 is reserved
47 + * @NL80211_STA_STAT_INACTIVE_TIME: time since last activity (u32, msecs)
48 + * @NL80211_STA_STAT_RX_BYTES: total received bytes (u32, from this station)
49 + * @NL80211_STA_STAT_TX_BYTES: total transmitted bytes (u32, to this station)
50 + * @__NL80211_STA_STAT_AFTER_LAST: internal
51 + * @NL80211_STA_STAT_MAX: highest possible station stats attribute
53 +enum nl80211_sta_stats {
54 + __NL80211_STA_STAT_INVALID,
55 + NL80211_STA_STAT_INACTIVE_TIME,
56 + NL80211_STA_STAT_RX_BYTES,
57 + NL80211_STA_STAT_TX_BYTES,
60 + __NL80211_STA_STAT_AFTER_LAST,
61 + NL80211_STA_STAT_MAX = __NL80211_STA_STAT_AFTER_LAST - 1
64 #endif /* __LINUX_NL80211_H */
65 --- everything.orig/include/net/cfg80211.h 2007-11-08 17:15:15.971532444 +0100
66 +++ everything/include/net/cfg80211.h 2007-11-08 17:17:00.891547364 +0100
67 @@ -130,6 +130,39 @@ struct station_parameters {
68 u8 supported_rates_len;
72 + * enum station_stats_flags - station statistics flags
74 + * Used by the driver to indicate which info in &struct station_stats
75 + * it has filled in during get_station().
77 + * @STATION_STAT_INACTIVE_TIME: @inactive_time filled
78 + * @STATION_STAT_RX_BYTES: @rx_bytes filled
79 + * @STATION_STAT_TX_BYTES: @tx_bytes filled
81 +enum station_stats_flags {
82 + STATION_STAT_INACTIVE_TIME = 1<<0,
83 + STATION_STAT_RX_BYTES = 1<<1,
84 + STATION_STAT_TX_BYTES = 1<<2,
88 + * struct station_stats - station statistics
90 + * Station information filled by driver for get_station().
92 + * @filled: bitflag of flags from &enum station_stats_flags
93 + * @inactive_time: time since last station activity (tx/rx) in milliseconds
94 + * @rx_bytes: bytes received from this station
95 + * @tx_bytes: bytes transmitted to this station
97 +struct station_stats {
104 /* from net/wireless.h */
107 @@ -209,6 +242,8 @@ struct cfg80211_ops {
109 int (*change_station)(struct wiphy *wiphy, struct net_device *dev,
110 u8 *mac, struct station_parameters *params);
111 + int (*get_station)(struct wiphy *wiphy, struct net_device *dev,
112 + u8 *mac, struct station_stats *stats);
115 #endif /* __NET_CFG80211_H */
116 --- everything.orig/net/wireless/nl80211.c 2007-11-08 17:15:15.981533909 +0100
117 +++ everything/net/wireless/nl80211.c 2007-11-08 17:17:00.901534235 +0100
118 @@ -751,9 +751,89 @@ static int parse_station_flags(struct nl
122 +static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
123 + int flags, struct net_device *dev,
124 + u8 *mac_addr, struct station_stats *stats)
127 + struct nlattr *statsattr;
129 + hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_STATION);
133 + NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex);
134 + NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr);
136 + statsattr = nla_nest_start(msg, NL80211_ATTR_STA_STATS);
138 + goto nla_put_failure;
139 + if (stats->filled & STATION_STAT_INACTIVE_TIME)
140 + NLA_PUT_U32(msg, NL80211_STA_STAT_INACTIVE_TIME,
141 + stats->inactive_time);
142 + if (stats->filled & STATION_STAT_RX_BYTES)
143 + NLA_PUT_U32(msg, NL80211_STA_STAT_RX_BYTES,
145 + if (stats->filled & STATION_STAT_TX_BYTES)
146 + NLA_PUT_U32(msg, NL80211_STA_STAT_TX_BYTES,
149 + nla_nest_end(msg, statsattr);
151 + return genlmsg_end(msg, hdr);
154 + return genlmsg_cancel(msg, hdr);
158 static int nl80211_get_station(struct sk_buff *skb, struct genl_info *info)
160 - return -EOPNOTSUPP;
161 + struct cfg80211_registered_device *drv;
163 + struct net_device *dev;
164 + struct station_stats stats;
165 + struct sk_buff *msg;
166 + u8 *mac_addr = NULL;
168 + memset(&stats, 0, sizeof(stats));
170 + if (!info->attrs[NL80211_ATTR_MAC])
173 + mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
175 + err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
179 + if (!drv->ops->get_station) {
185 + err = drv->ops->get_station(&drv->wiphy, dev, mac_addr, &stats);
188 + msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
192 + if (nl80211_send_station(msg, info->snd_pid, info->snd_seq, 0,
193 + dev, mac_addr, &stats) < 0)
196 + err = genlmsg_unicast(msg, info->snd_pid);
203 + cfg80211_put_dev(drv);