Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 78612
b: refs/heads/master
c: fd5b74d
h: refs/heads/master
v: v3
  • Loading branch information
Johannes Berg authored and David S. Miller committed Jan 28, 2008
1 parent d1f796b commit 30dd4c8
Show file tree
Hide file tree
Showing 4 changed files with 145 additions and 2 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 5727ef1b2e797a1922f5bc239b6afb2b4cfb80bc
refs/heads/master: fd5b74dcb88cfc109d6576b22deaef6f47f82c12
28 changes: 28 additions & 0 deletions trunk/include/linux/nl80211.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 */

Expand Down Expand Up @@ -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 */
35 changes: 35 additions & 0 deletions trunk/include/net/cfg80211.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -210,6 +243,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 */
82 changes: 81 additions & 1 deletion trunk/net/wireless/nl80211.c
Original file line number Diff line number Diff line change
Expand Up @@ -750,9 +750,89 @@ static int parse_station_flags(struct nlattr *nla, u32 *staflags)
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;
}

/*
Expand Down

0 comments on commit 30dd4c8

Please sign in to comment.