Skip to content

Commit

Permalink
cfg80211: allow including station info in delete event
Browse files Browse the repository at this point in the history
When a station is removed, its statistics may be interesting to
userspace, for example for further aggregation of statistics of
all stations that ever connected to an AP.

Introduce a new cfg80211_del_sta_sinfo() function (and make the
cfg80211_del_sta() a static inline calling it) to allow passing
a struct station_info along with this, and send the data in the
nl80211 event message.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
  • Loading branch information
Johannes Berg committed Jan 8, 2015
1 parent 052536a commit cf5ead8
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 23 deletions.
16 changes: 15 additions & 1 deletion include/net/cfg80211.h
Original file line number Diff line number Diff line change
Expand Up @@ -4591,14 +4591,28 @@ void cfg80211_remain_on_channel_expired(struct wireless_dev *wdev, u64 cookie,
void cfg80211_new_sta(struct net_device *dev, const u8 *mac_addr,
struct station_info *sinfo, gfp_t gfp);

/**
* cfg80211_del_sta_sinfo - notify userspace about deletion of a station
* @dev: the netdev
* @mac_addr: the station's address
* @sinfo: the station information/statistics
* @gfp: allocation flags
*/
void cfg80211_del_sta_sinfo(struct net_device *dev, const u8 *mac_addr,
struct station_info *sinfo, gfp_t gfp);

/**
* cfg80211_del_sta - notify userspace about deletion of a station
*
* @dev: the netdev
* @mac_addr: the station's address
* @gfp: allocation flags
*/
void cfg80211_del_sta(struct net_device *dev, const u8 *mac_addr, gfp_t gfp);
static inline void cfg80211_del_sta(struct net_device *dev,
const u8 *mac_addr, gfp_t gfp)
{
cfg80211_del_sta_sinfo(dev, mac_addr, NULL, gfp);
}

/**
* cfg80211_conn_failed - connection request failed notification
Expand Down
38 changes: 16 additions & 22 deletions net/wireless/nl80211.c
Original file line number Diff line number Diff line change
Expand Up @@ -3650,16 +3650,16 @@ static bool nl80211_put_signal(struct sk_buff *msg, u8 mask, s8 *signal,
return true;
}

static int nl80211_send_station(struct sk_buff *msg, u32 portid, u32 seq,
int flags,
static int nl80211_send_station(struct sk_buff *msg, u32 cmd, u32 portid,
u32 seq, int flags,
struct cfg80211_registered_device *rdev,
struct net_device *dev,
const u8 *mac_addr, struct station_info *sinfo)
{
void *hdr;
struct nlattr *sinfoattr, *bss_param;

hdr = nl80211hdr_put(msg, portid, seq, flags, NL80211_CMD_NEW_STATION);
hdr = nl80211hdr_put(msg, portid, seq, flags, cmd);
if (!hdr)
return -1;

Expand Down Expand Up @@ -3854,7 +3854,7 @@ static int nl80211_dump_station(struct sk_buff *skb,
if (err)
goto out_err;

if (nl80211_send_station(skb,
if (nl80211_send_station(skb, NL80211_CMD_NEW_STATION,
NETLINK_CB(cb->skb).portid,
cb->nlh->nlmsg_seq, NLM_F_MULTI,
rdev, wdev->netdev, mac_addr,
Expand Down Expand Up @@ -3901,7 +3901,8 @@ static int nl80211_get_station(struct sk_buff *skb, struct genl_info *info)
if (!msg)
return -ENOMEM;

if (nl80211_send_station(msg, info->snd_portid, info->snd_seq, 0,
if (nl80211_send_station(msg, NL80211_CMD_NEW_STATION,
info->snd_portid, info->snd_seq, 0,
rdev, dev, mac_addr, &sinfo) < 0) {
nlmsg_free(msg);
return -ENOBUFS;
Expand Down Expand Up @@ -11687,7 +11688,7 @@ void cfg80211_new_sta(struct net_device *dev, const u8 *mac_addr,
if (!msg)
return;

if (nl80211_send_station(msg, 0, 0, 0,
if (nl80211_send_station(msg, NL80211_CMD_NEW_STATION, 0, 0, 0,
rdev, dev, mac_addr, sinfo) < 0) {
nlmsg_free(msg);
return;
Expand All @@ -11698,40 +11699,33 @@ void cfg80211_new_sta(struct net_device *dev, const u8 *mac_addr,
}
EXPORT_SYMBOL(cfg80211_new_sta);

void cfg80211_del_sta(struct net_device *dev, const u8 *mac_addr, gfp_t gfp)
void cfg80211_del_sta_sinfo(struct net_device *dev, const u8 *mac_addr,
struct station_info *sinfo, gfp_t gfp)
{
struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
struct sk_buff *msg;
void *hdr;
struct station_info empty_sinfo = {};

if (!sinfo)
sinfo = &empty_sinfo;

trace_cfg80211_del_sta(dev, mac_addr);

msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
if (!msg)
return;

hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_DEL_STATION);
if (!hdr) {
if (nl80211_send_station(msg, NL80211_CMD_DEL_STATION, 0, 0, 0,
rdev, dev, mac_addr, sinfo)) {
nlmsg_free(msg);
return;
}

if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr))
goto nla_put_failure;

genlmsg_end(msg, hdr);

genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
NL80211_MCGRP_MLME, gfp);
return;

nla_put_failure:
genlmsg_cancel(msg, hdr);
nlmsg_free(msg);
}
EXPORT_SYMBOL(cfg80211_del_sta);
EXPORT_SYMBOL(cfg80211_del_sta_sinfo);

void cfg80211_conn_failed(struct net_device *dev, const u8 *mac_addr,
enum nl80211_connect_failed_reason reason,
Expand Down

0 comments on commit cf5ead8

Please sign in to comment.