cfg80211: add channel switch started notification

Add a new NL80211_CH_SWITCH_STARTED_NOTIFY message that can be sent to
the userspace when a channel switch process has started.  This allows
userspace to take action, for instance, by requesting other interfaces
to switch channel as necessary.

This patch introduces a function that allows the drivers to send this
notification.  It should be used when the driver starts processing a
channel switch initiated by a remote device (eg. when a STA receives a
CSA from the AP) and when it successfully starts a userspace-triggered
channel switch (eg. when hostapd triggers a channel swith in the AP).

Signed-off-by: Luciano Coelho <luciano.coelho@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
Luciano Coelho 2014-11-07 14:31:35 +02:00 committed by Johannes Berg
parent 127f10ec60
commit f8d7552e94
4 changed files with 66 additions and 3 deletions

View File

@ -4719,6 +4719,20 @@ bool cfg80211_reg_can_beacon(struct wiphy *wiphy,
void cfg80211_ch_switch_notify(struct net_device *dev,
struct cfg80211_chan_def *chandef);
/*
* cfg80211_ch_switch_started_notify - notify channel switch start
* @dev: the device on which the channel switch started
* @chandef: the future channel definition
* @count: the number of TBTTs until the channel switch happens
*
* Inform the userspace about the channel switch that has just
* started, so that it can take appropriate actions (eg. starting
* channel switch on other vifs), if necessary.
*/
void cfg80211_ch_switch_started_notify(struct net_device *dev,
struct cfg80211_chan_def *chandef,
u8 count);
/**
* ieee80211_operating_class_to_band - convert operating class to band
*

View File

@ -645,6 +645,15 @@
* %NL80211_ATTR_IFINDEX is now on %NL80211_ATTR_WIPHY_FREQ and the
* attributes determining channel width.
*
* @NL80211_CMD_CH_SWITCH_STARTED_NOTIFY: Notify that a channel switch
* has been started on an interface, regardless of the initiator
* (ie. whether it was requested from a remote device or
* initiated on our own). It indicates that
* %NL80211_ATTR_IFINDEX will be on %NL80211_ATTR_WIPHY_FREQ
* after %NL80211_ATTR_CH_SWITCH_COUNT TBTT's. The userspace may
* decide to react to this indication by requesting other
* interfaces to change channel as well.
*
* @NL80211_CMD_START_P2P_DEVICE: Start the given P2P Device, identified by
* its %NL80211_ATTR_WDEV identifier. It must have been created with
* %NL80211_CMD_NEW_INTERFACE previously. After it has been started, the
@ -930,6 +939,8 @@ enum nl80211_commands {
NL80211_CMD_JOIN_OCB,
NL80211_CMD_LEAVE_OCB,
NL80211_CMD_CH_SWITCH_STARTED_NOTIFY,
/* add new commands above here */
/* used to define NL80211_CMD_MAX below */

View File

@ -11653,7 +11653,9 @@ EXPORT_SYMBOL(cfg80211_pmksa_candidate_notify);
static void nl80211_ch_switch_notify(struct cfg80211_registered_device *rdev,
struct net_device *netdev,
struct cfg80211_chan_def *chandef,
gfp_t gfp)
gfp_t gfp,
enum nl80211_commands notif,
u8 count)
{
struct sk_buff *msg;
void *hdr;
@ -11662,7 +11664,7 @@ static void nl80211_ch_switch_notify(struct cfg80211_registered_device *rdev,
if (!msg)
return;
hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_CH_SWITCH_NOTIFY);
hdr = nl80211hdr_put(msg, 0, 0, 0, notif);
if (!hdr) {
nlmsg_free(msg);
return;
@ -11674,6 +11676,10 @@ static void nl80211_ch_switch_notify(struct cfg80211_registered_device *rdev,
if (nl80211_send_chandef(msg, chandef))
goto nla_put_failure;
if ((notif == NL80211_CMD_CH_SWITCH_STARTED_NOTIFY) &&
(nla_put_u32(msg, NL80211_ATTR_CH_SWITCH_COUNT, count)))
goto nla_put_failure;
genlmsg_end(msg, hdr);
genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
@ -11704,10 +11710,26 @@ void cfg80211_ch_switch_notify(struct net_device *dev,
wdev->chandef = *chandef;
wdev->preset_chandef = *chandef;
nl80211_ch_switch_notify(rdev, dev, chandef, GFP_KERNEL);
nl80211_ch_switch_notify(rdev, dev, chandef, GFP_KERNEL,
NL80211_CMD_CH_SWITCH_NOTIFY, 0);
}
EXPORT_SYMBOL(cfg80211_ch_switch_notify);
void cfg80211_ch_switch_started_notify(struct net_device *dev,
struct cfg80211_chan_def *chandef,
u8 count)
{
struct wireless_dev *wdev = dev->ieee80211_ptr;
struct wiphy *wiphy = wdev->wiphy;
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
trace_cfg80211_ch_switch_started_notify(dev, chandef);
nl80211_ch_switch_notify(rdev, dev, chandef, GFP_KERNEL,
NL80211_CMD_CH_SWITCH_STARTED_NOTIFY, count);
}
EXPORT_SYMBOL(cfg80211_ch_switch_started_notify);
void cfg80211_cqm_txe_notify(struct net_device *dev,
const u8 *peer, u32 num_packets,
u32 rate, u32 intvl, gfp_t gfp)

View File

@ -2355,6 +2355,22 @@ TRACE_EVENT(cfg80211_ch_switch_notify,
NETDEV_PR_ARG, CHAN_DEF_PR_ARG)
);
TRACE_EVENT(cfg80211_ch_switch_started_notify,
TP_PROTO(struct net_device *netdev,
struct cfg80211_chan_def *chandef),
TP_ARGS(netdev, chandef),
TP_STRUCT__entry(
NETDEV_ENTRY
CHAN_DEF_ENTRY
),
TP_fast_assign(
NETDEV_ASSIGN;
CHAN_DEF_ASSIGN(chandef);
),
TP_printk(NETDEV_PR_FMT ", " CHAN_DEF_PR_FMT,
NETDEV_PR_ARG, CHAN_DEF_PR_ARG)
);
TRACE_EVENT(cfg80211_radar_event,
TP_PROTO(struct wiphy *wiphy, struct cfg80211_chan_def *chandef),
TP_ARGS(wiphy, chandef),