* [PATCHv5 0/8] Add DFS master ability
@ 2012-12-13 13:58 Simon Wunderlich
2012-12-13 13:58 ` [PATCHv5 1/8] cfg80211: add CHAN_MODE_SINGLE_ONLY for DFS use Simon Wunderlich
` (8 more replies)
0 siblings, 9 replies; 27+ messages in thread
From: Simon Wunderlich @ 2012-12-13 13:58 UTC (permalink / raw)
To: linux-wireless
Cc: johannes, victorg, linville, kgiori, zefir.kurtisi, adrian, j,
coelho, assaf, igalc, nbd, mathias.kretschmer, Simon Wunderlich
I'm picking up and extending Victor Goldenshteins work on DFS
ability in AP mode. See changelog in the various patches for
details. The main changes are:
* the freuency within start_radar_detection is now used for the
channel, dependency on __nl80211_set_channel is removed
* enable_tx command removed, respective checks are now in start_ap
* ap channel switch implicitly stops AP when changing to a radar
channel. Userspace must then restart radar detection and can
start the AP again after that
=> both changes from above are done to have a clean state of
channel - low level driver should not care about whether
a channel is a radar channel and when to be quiet. This way, all
the control over the channel state keeps in nl80211.
* add new SINGLE_ONLY channel mode to prevent other MultiSSID/MultiVIF use
* prevent scan/roc to run at the same time as the AP
* move dfs capability checks into reg_can_beacon()
* change most of the functions to use the new chandef instead of
channel, channel_type ...
* rebased on latest master, of course
I'm sending this as patch to keep the versioning, although it can be
considered as RFC, I would be suprised if all single channel/single
interface aspects were considered correctly. :)
The implementation works for me [tm] with a dummy dfs-implementation
in ath9k and a patched hostapd - the hostapd patches will be sent later
once this patchset is in shape (Victors patches plus some dirty
modifications, need to clean it up first).
Any comment/review/etc are very much appreciated!
Thanks,
Simon
Simon Wunderlich (4):
cfg80211: add CHAN_MODE_SINGLE_ONLY for DFS use
cfg/mac80211: add dfs capability to cfg80211_reg_can_beacon()
mac80211: check radar interaction with scan and roc
nl80211: allow DFS in start_ap
Victor Goldenshtein (4):
nl80211/cfg80211: add radar detection command/event
mac80211: add radar detection command/event
nl80211/cfg80211: add ap channel switch command
mac80211: add ap channel switch command/event
include/net/cfg80211.h | 68 ++++++++++++++-
include/net/mac80211.h | 46 ++++++++++
include/uapi/linux/nl80211.h | 39 +++++++++
net/mac80211/cfg.c | 65 +++++++++++++-
net/mac80211/driver-ops.h | 26 ++++++
net/mac80211/ibss.c | 2 +-
net/mac80211/ieee80211_i.h | 7 ++
net/mac80211/iface.c | 6 ++
net/mac80211/main.c | 2 +
net/mac80211/mlme.c | 77 +++++++++++++++++
net/mac80211/scan.c | 3 +
net/mac80211/trace.h | 121 ++++++++++++++++++++++++++
net/wireless/chan.c | 23 +++--
net/wireless/core.h | 1 +
net/wireless/mesh.c | 2 +-
net/wireless/mlme.c | 32 ++++++-
net/wireless/nl80211.c | 194 ++++++++++++++++++++++++++++++++++++++++--
net/wireless/nl80211.h | 9 +-
net/wireless/trace.h | 11 ++-
net/wireless/util.c | 14 +++
20 files changed, 723 insertions(+), 25 deletions(-)
--
1.7.10.4
^ permalink raw reply [flat|nested] 27+ messages in thread
* [PATCHv5 1/8] cfg80211: add CHAN_MODE_SINGLE_ONLY for DFS use
2012-12-13 13:58 [PATCHv5 0/8] Add DFS master ability Simon Wunderlich
@ 2012-12-13 13:58 ` Simon Wunderlich
2013-01-02 13:34 ` Johannes Berg
2012-12-13 13:58 ` [PATCHv5 2/8] cfg/mac80211: add dfs capability to cfg80211_reg_can_beacon() Simon Wunderlich
` (7 subsequent siblings)
8 siblings, 1 reply; 27+ messages in thread
From: Simon Wunderlich @ 2012-12-13 13:58 UTC (permalink / raw)
To: linux-wireless
Cc: johannes, victorg, linville, kgiori, zefir.kurtisi, adrian, j,
coelho, assaf, igalc, nbd, mathias.kretschmer, Simon Wunderlich
In DFS, we don't allow multiple virtual interfaces on one phy
for now, because synchronizing channel state between them is not
trivial and not implemented so far. Therefore, add another channel
mode to seperate this.
Signed-off-by: Simon Wunderlich <siwu@hrz.tu-chemnitz.de>
---
net/wireless/core.h | 1 +
net/wireless/util.c | 14 ++++++++++++++
2 files changed, 15 insertions(+)
diff --git a/net/wireless/core.h b/net/wireless/core.h
index 3563097..642587c 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -257,6 +257,7 @@ enum cfg80211_chan_mode {
CHAN_MODE_UNDEFINED,
CHAN_MODE_SHARED,
CHAN_MODE_EXCLUSIVE,
+ CHAN_MODE_SINGLE_ONLY,
};
struct cfg80211_beacon_registration {
diff --git a/net/wireless/util.c b/net/wireless/util.c
index 16d76a8..18a3349 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -1220,6 +1220,10 @@ int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev,
case CHAN_MODE_EXCLUSIVE:
num_different_channels++;
break;
+ case CHAN_MODE_SINGLE_ONLY:
+ used_channels[0] = chan;
+ num_different_channels++;
+ break;
}
list_for_each_entry(wdev_iter, &rdev->wdev_list, list) {
@@ -1268,6 +1272,12 @@ int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev,
case CHAN_MODE_EXCLUSIVE:
num_different_channels++;
break;
+ case CHAN_MODE_SINGLE_ONLY:
+ /* can't add any more interfaces when a single channel
+ * has already been added.
+ */
+ return -EBUSY;
+ break;
}
num[wdev_iter->iftype]++;
@@ -1278,6 +1288,10 @@ int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev,
if (total == 1)
return 0;
+ /* can't add single mode to any other interfaces. */
+ if ((total > 1) && (chanmode == CHAN_MODE_SINGLE_ONLY))
+ return -EBUSY;
+
for (i = 0; i < rdev->wiphy.n_iface_combinations; i++) {
const struct ieee80211_iface_combination *c;
struct ieee80211_iface_limit *limits;
--
1.7.10.4
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PATCHv5 2/8] cfg/mac80211: add dfs capability to cfg80211_reg_can_beacon()
2012-12-13 13:58 [PATCHv5 0/8] Add DFS master ability Simon Wunderlich
2012-12-13 13:58 ` [PATCHv5 1/8] cfg80211: add CHAN_MODE_SINGLE_ONLY for DFS use Simon Wunderlich
@ 2012-12-13 13:58 ` Simon Wunderlich
2013-01-02 13:36 ` Johannes Berg
2012-12-13 13:58 ` [PATCHv5 3/8] nl80211/cfg80211: add radar detection command/event Simon Wunderlich
` (6 subsequent siblings)
8 siblings, 1 reply; 27+ messages in thread
From: Simon Wunderlich @ 2012-12-13 13:58 UTC (permalink / raw)
To: linux-wireless
Cc: johannes, victorg, linville, kgiori, zefir.kurtisi, adrian, j,
coelho, assaf, igalc, nbd, mathias.kretschmer, Simon Wunderlich
When checking if the channel can be used for beacons, the decision
should be made depending on whether DFS is supported.
Signed-off-by: Simon Wunderlich <siwu@hrz.tu-chemnitz.de>
---
include/net/cfg80211.h | 4 +++-
net/mac80211/ibss.c | 2 +-
net/wireless/chan.c | 18 +++++++++++-------
net/wireless/mesh.c | 2 +-
net/wireless/nl80211.c | 7 ++++---
net/wireless/trace.h | 11 +++++++----
6 files changed, 27 insertions(+), 17 deletions(-)
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 8e6a6b7..1d22919 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -3684,12 +3684,14 @@ void cfg80211_report_obss_beacon(struct wiphy *wiphy,
* cfg80211_reg_can_beacon - check if beaconing is allowed
* @wiphy: the wiphy
* @chandef: the channel definition
+ * @dfs_capab: supported DFS bandwidth
*
* This function returns true if there is no secondary channel or the secondary
* channel(s) can be used for beaconing (i.e. is not a radar channel etc.)
*/
bool cfg80211_reg_can_beacon(struct wiphy *wiphy,
- struct cfg80211_chan_def *chandef);
+ struct cfg80211_chan_def *chandef,
+ enum nl80211_chan_width dfs_capab);
/*
* cfg80211_ch_switch_notify - update wdev channel and notify userspace
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index 8881fc7..8509386 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -80,7 +80,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
sdata->drop_unencrypted = capability & WLAN_CAPABILITY_PRIVACY ? 1 : 0;
cfg80211_chandef_create(&chandef, chan, ifibss->channel_type);
- if (!cfg80211_reg_can_beacon(local->hw.wiphy, &chandef)) {
+ if (!cfg80211_reg_can_beacon(local->hw.wiphy, &chandef, -1)) {
chandef.width = NL80211_CHAN_WIDTH_20;
chandef.center_freq1 = chan->center_freq;
}
diff --git a/net/wireless/chan.c b/net/wireless/chan.c
index a7990bb..18888f6 100644
--- a/net/wireless/chan.c
+++ b/net/wireless/chan.c
@@ -280,17 +280,21 @@ bool cfg80211_chandef_usable(struct wiphy *wiphy,
EXPORT_SYMBOL(cfg80211_chandef_usable);
bool cfg80211_reg_can_beacon(struct wiphy *wiphy,
- struct cfg80211_chan_def *chandef)
+ struct cfg80211_chan_def *chandef,
+ enum nl80211_chan_width dfs_capab)
{
bool res;
+ u32 prohibited_flags;
- trace_cfg80211_reg_can_beacon(wiphy, chandef);
+ trace_cfg80211_reg_can_beacon(wiphy, chandef, dfs_capab);
- res = cfg80211_chandef_usable(wiphy, chandef,
- IEEE80211_CHAN_DISABLED |
- IEEE80211_CHAN_PASSIVE_SCAN |
- IEEE80211_CHAN_NO_IBSS |
- IEEE80211_CHAN_RADAR);
+ prohibited_flags = IEEE80211_CHAN_DISABLED;
+ if (chandef->width > dfs_capab)
+ prohibited_flags |= IEEE80211_CHAN_PASSIVE_SCAN |
+ IEEE80211_CHAN_NO_IBSS |
+ IEEE80211_CHAN_RADAR;
+
+ res = cfg80211_chandef_usable(wiphy, chandef, prohibited_flags);
trace_cfg80211_return_bool(res);
return res;
diff --git a/net/wireless/mesh.c b/net/wireless/mesh.c
index f9d6ce5..798477b 100644
--- a/net/wireless/mesh.c
+++ b/net/wireless/mesh.c
@@ -150,7 +150,7 @@ int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev,
setup->chandef.center_freq1 = setup->chandef.chan->center_freq;
}
- if (!cfg80211_reg_can_beacon(&rdev->wiphy, &setup->chandef))
+ if (!cfg80211_reg_can_beacon(&rdev->wiphy, &setup->chandef, -1))
return -EINVAL;
err = cfg80211_can_use_chan(rdev, wdev, setup->chandef.chan,
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index f45706a..aeea068 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -1453,7 +1453,7 @@ static int __nl80211_set_channel(struct cfg80211_registered_device *rdev,
result = -EBUSY;
break;
}
- if (!cfg80211_reg_can_beacon(&rdev->wiphy, &chandef)) {
+ if (!cfg80211_reg_can_beacon(&rdev->wiphy, &chandef, -1)) {
result = -EINVAL;
break;
}
@@ -2713,7 +2713,8 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
} else if (!nl80211_get_ap_channel(rdev, ¶ms))
return -EINVAL;
- if (!cfg80211_reg_can_beacon(&rdev->wiphy, ¶ms.chandef))
+ if (!cfg80211_reg_can_beacon(&rdev->wiphy, ¶ms.chandef,
+ -1))
return -EINVAL;
mutex_lock(&rdev->devlist_mtx);
@@ -5504,7 +5505,7 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info)
if (err)
return err;
- if (!cfg80211_reg_can_beacon(&rdev->wiphy, &ibss.chandef))
+ if (!cfg80211_reg_can_beacon(&rdev->wiphy, &ibss.chandef, -1))
return -EINVAL;
if (ibss.chandef.width > NL80211_CHAN_WIDTH_40)
diff --git a/net/wireless/trace.h b/net/wireless/trace.h
index 2134576..e311e49 100644
--- a/net/wireless/trace.h
+++ b/net/wireless/trace.h
@@ -2019,18 +2019,21 @@ TRACE_EVENT(cfg80211_cqm_rssi_notify,
);
TRACE_EVENT(cfg80211_reg_can_beacon,
- TP_PROTO(struct wiphy *wiphy, struct cfg80211_chan_def *chandef),
- TP_ARGS(wiphy, chandef),
+ TP_PROTO(struct wiphy *wiphy, struct cfg80211_chan_def *chandef,
+ enum nl80211_chan_width dfs_capab),
+ TP_ARGS(wiphy, chandef, dfs_capab),
TP_STRUCT__entry(
WIPHY_ENTRY
CHAN_DEF_ENTRY
+ __field(int, dfs_capab)
),
TP_fast_assign(
WIPHY_ASSIGN;
CHAN_DEF_ASSIGN(chandef);
+ __entry->dfs_capab = dfs_capab;
),
- TP_printk(WIPHY_PR_FMT ", " CHAN_DEF_PR_FMT,
- WIPHY_PR_ARG, CHAN_DEF_PR_ARG)
+ TP_printk(WIPHY_PR_FMT ", " CHAN_DEF_PR_FMT " dfs_capability: %d",
+ WIPHY_PR_ARG, CHAN_DEF_PR_ARG, __entry->dfs_capab)
);
TRACE_EVENT(cfg80211_ch_switch_notify,
--
1.7.10.4
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PATCHv5 3/8] nl80211/cfg80211: add radar detection command/event
2012-12-13 13:58 [PATCHv5 0/8] Add DFS master ability Simon Wunderlich
2012-12-13 13:58 ` [PATCHv5 1/8] cfg80211: add CHAN_MODE_SINGLE_ONLY for DFS use Simon Wunderlich
2012-12-13 13:58 ` [PATCHv5 2/8] cfg/mac80211: add dfs capability to cfg80211_reg_can_beacon() Simon Wunderlich
@ 2012-12-13 13:58 ` Simon Wunderlich
2013-01-02 13:39 ` Johannes Berg
2012-12-13 13:58 ` [PATCHv5 4/8] mac80211: " Simon Wunderlich
` (5 subsequent siblings)
8 siblings, 1 reply; 27+ messages in thread
From: Simon Wunderlich @ 2012-12-13 13:58 UTC (permalink / raw)
To: linux-wireless
Cc: johannes, victorg, linville, kgiori, zefir.kurtisi, adrian, j,
coelho, assaf, igalc, nbd, mathias.kretschmer, Simon Wunderlich
From: Victor Goldenshtein <victorg@ti.com>
Add new NL80211_CMD_RADAR_DETECT, which triggers radar
detection in the driver/FW, this command will also notify
usermode with 'radar detected' event.
Once radar detection has started it should continuously
monitor for radars as long as the channel is active.
Add new NL80211_FEATURE_20MHZ_DFS attribute which
indicates that driver/HW supports radar detection
on 20MHz channel bandwidth.
Signed-off-by: Victor Goldenshtein <victorg@ti.com>
[changes:
* change to chandef
* add dfs_nlportid and check it
* rebase on current master]
Signed-off-by: Simon Wunderlich <siwu@hrz.tu-chemnitz.de>
---
include/net/cfg80211.h | 26 ++++++++++++
include/uapi/linux/nl80211.h | 10 +++++
net/wireless/mlme.c | 13 ++++++
net/wireless/nl80211.c | 96 ++++++++++++++++++++++++++++++++++++++++++
net/wireless/nl80211.h | 6 +++
5 files changed, 151 insertions(+)
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 1d22919..3740b57 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -133,6 +133,11 @@ enum ieee80211_channel_flags {
* to enable this, this is useful only on 5 GHz band.
* @orig_mag: internal use
* @orig_mpwr: internal use
+ * @radar_detect_timeout: this timeout indicates the end of the channel
+ * availability check for radar channels (in jiffies), only after this
+ * period the user may initiate the tx on the channel.
+ * @cac_type: indicates that channel availability check is started for this
+ * channel type.
*/
struct ieee80211_channel {
enum ieee80211_band band;
@@ -145,6 +150,9 @@ struct ieee80211_channel {
bool beacon_found;
u32 orig_flags;
int orig_mag, orig_mpwr;
+ unsigned long radar_detect_timeout;
+ enum nl80211_channel_type cac_type;
+ bool cac_started;
};
/**
@@ -1763,6 +1771,8 @@ struct cfg80211_gtk_rekey_data {
*
* @start_p2p_device: Start the given P2P device.
* @stop_p2p_device: Stop the given P2P device.
+ *
+ * @start_radar_detection: Start radar detection in the driver.
*/
struct cfg80211_ops {
int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
@@ -1983,6 +1993,10 @@ struct cfg80211_ops {
struct wireless_dev *wdev);
void (*stop_p2p_device)(struct wiphy *wiphy,
struct wireless_dev *wdev);
+
+ int (*start_radar_detection)(struct wiphy *wiphy,
+ struct net_device *dev,
+ struct cfg80211_chan_def *chandef);
};
/*
@@ -2598,6 +2612,7 @@ struct wireless_dev {
int beacon_interval;
u32 ap_unexpected_nlportid;
+ u32 dfs_nlportid;
#ifdef CONFIG_CFG80211_WEXT
/* wext data */
@@ -3575,6 +3590,17 @@ void cfg80211_cqm_rssi_notify(struct net_device *dev,
gfp_t gfp);
/**
+ * cfg80211_radar_detected - radar detection event
+ * @dev: network device
+ * @chan: radar detected on this channel.
+ * @gfp: context flags
+ *
+ * This function is called when a radar is detected on the current channel.
+ */
+void cfg80211_radar_detected(struct net_device *dev,
+ struct ieee80211_channel *chan, gfp_t gfp);
+
+/**
* cfg80211_cqm_pktloss_notify - notify userspace about packetloss to peer
* @dev: network device
* @peer: peer's MAC address
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index e3e19f8..2303f86 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -586,6 +586,9 @@
* @NL80211_CMD_SET_MCAST_RATE: Change the rate used to send multicast frames
* for IBSS or MESH vif.
*
+ * @NL80211_CMD_RADAR_DETECT: Start radar detection in the driver/HW. Once
+ * radar detected usermode notified with this event.
+ *
* @NL80211_CMD_MAX: highest used command number
* @__NL80211_CMD_AFTER_LAST: internal use
*/
@@ -736,6 +739,8 @@ enum nl80211_commands {
NL80211_CMD_SET_MCAST_RATE,
+ NL80211_CMD_RADAR_DETECT,
+
/* add new commands above here */
/* used to define NL80211_CMD_MAX below */
@@ -1635,6 +1640,8 @@ enum nl80211_attrs {
#define NL80211_CQM_TXE_MAX_INTVL 1800
+#define NL80211_DFS_MIN_CAC_TIME_MS 60000
+
/**
* enum nl80211_iftype - (virtual) interface types
*
@@ -3140,6 +3147,8 @@ enum nl80211_ap_sme_features {
* setting
* @NL80211_FEATURE_P2P_GO_OPPPS: P2P GO implementation supports opportunistic
* powersave
+ * @NL80211_FEATURE_20MHZ_DFS: Radar detection is supported in the
+ * HW/driver on 20 MHz channel bandwidth.
*/
enum nl80211_feature_flags {
NL80211_FEATURE_SK_TX_STATUS = 1 << 0,
@@ -3155,6 +3164,7 @@ enum nl80211_feature_flags {
NL80211_FEATURE_NEED_OBSS_SCAN = 1 << 10,
NL80211_FEATURE_P2P_GO_CTWIN = 1 << 11,
NL80211_FEATURE_P2P_GO_OPPPS = 1 << 12,
+ NL80211_FEATURE_20MHZ_DFS = 1 << 13,
};
/**
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
index 5e8123e..02666e3 100644
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
@@ -1049,3 +1049,16 @@ bool cfg80211_rx_unexpected_4addr_frame(struct net_device *dev,
return ret;
}
EXPORT_SYMBOL(cfg80211_rx_unexpected_4addr_frame);
+
+void cfg80211_radar_detected(struct net_device *dev,
+ struct ieee80211_channel *chan, gfp_t gfp)
+{
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+ struct wiphy *wiphy = wdev->wiphy;
+ struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
+
+ chan->cac_started = false;
+
+ nl80211_radar_detected_notify(rdev, chan, dev, gfp);
+}
+EXPORT_SYMBOL(cfg80211_radar_detected);
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index aeea068..d49c0c2 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -4802,6 +4802,57 @@ static int nl80211_stop_sched_scan(struct sk_buff *skb,
return err;
}
+static int nl80211_start_radar_detection(struct sk_buff *skb,
+ struct genl_info *info)
+{
+ struct cfg80211_registered_device *rdev = info->user_ptr[0];
+ struct net_device *dev = info->user_ptr[1];
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+ struct cfg80211_chan_def chandef;
+ int err;
+
+ if (!(rdev->wiphy.features & NL80211_FEATURE_20MHZ_DFS))
+ return -EOPNOTSUPP;
+
+ err = nl80211_parse_chandef(rdev, info, &chandef);
+ if (err)
+ return err;
+
+ if (chandef.width > NL80211_CHAN_WIDTH_20)
+ return -EOPNOTSUPP;
+
+ if (!(chandef.chan->flags & IEEE80211_CHAN_RADAR))
+ return -EINVAL;
+
+ if (chandef.chan->cac_started)
+ return -EBUSY;
+
+ if (!rdev->ops->start_radar_detection)
+ return -EOPNOTSUPP;
+
+ if (wdev->dfs_nlportid && info->snd_portid != wdev->dfs_nlportid)
+ return -EBUSY;
+
+ mutex_lock(&rdev->devlist_mtx);
+ err = cfg80211_can_use_chan(rdev, wdev, chandef.chan,
+ CHAN_MODE_SINGLE_ONLY);
+ mutex_unlock(&rdev->devlist_mtx);
+
+ if (err)
+ return err;
+
+ err = rdev->ops->start_radar_detection(&rdev->wiphy, dev, &chandef);
+ if (!err) {
+ wdev->preset_chandef = chandef;
+ chandef.chan->cac_started = true;
+ chandef.chan->radar_detect_timeout = jiffies +
+ msecs_to_jiffies(NL80211_DFS_MIN_CAC_TIME_MS);
+ wdev->dfs_nlportid = info->snd_portid;
+ }
+
+ return err;
+}
+
static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb,
u32 seq, int flags,
struct cfg80211_registered_device *rdev,
@@ -7785,6 +7836,14 @@ static struct genl_ops nl80211_ops[] = {
.internal_flags = NL80211_FLAG_NEED_NETDEV |
NL80211_FLAG_NEED_RTNL,
},
+ {
+ .cmd = NL80211_CMD_RADAR_DETECT,
+ .doit = nl80211_start_radar_detection,
+ .policy = nl80211_policy,
+ .flags = GENL_ADMIN_PERM,
+ .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
+ NL80211_FLAG_NEED_RTNL,
+ },
};
static struct genl_multicast_group nl80211_mlme_mcgrp = {
@@ -8982,6 +9041,43 @@ nl80211_send_cqm_txe_notify(struct cfg80211_registered_device *rdev,
}
void
+nl80211_radar_detected_notify(struct cfg80211_registered_device *rdev,
+ struct ieee80211_channel *chan,
+ struct net_device *netdev, gfp_t gfp)
+{
+ struct sk_buff *msg;
+ void *hdr;
+
+ msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
+ if (!msg)
+ return;
+
+ hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_RADAR_DETECT);
+ if (!hdr) {
+ nlmsg_free(msg);
+ return;
+ }
+
+ if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
+ nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) ||
+ nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, chan->center_freq))
+ goto nla_put_failure;
+
+ if (genlmsg_end(msg, hdr) < 0) {
+ nlmsg_free(msg);
+ return;
+ }
+
+ genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
+ nl80211_mlme_mcgrp.id, gfp);
+ return;
+
+ nla_put_failure:
+ genlmsg_cancel(msg, hdr);
+ nlmsg_free(msg);
+}
+
+void
nl80211_send_cqm_pktloss_notify(struct cfg80211_registered_device *rdev,
struct net_device *netdev, const u8 *peer,
u32 num_packets, gfp_t gfp)
diff --git a/net/wireless/nl80211.h b/net/wireless/nl80211.h
index 2acba84..28b9a34 100644
--- a/net/wireless/nl80211.h
+++ b/net/wireless/nl80211.h
@@ -108,6 +108,12 @@ nl80211_send_cqm_rssi_notify(struct cfg80211_registered_device *rdev,
struct net_device *netdev,
enum nl80211_cqm_rssi_threshold_event rssi_event,
gfp_t gfp);
+
+void
+nl80211_radar_detected_notify(struct cfg80211_registered_device *rdev,
+ struct ieee80211_channel *chan,
+ struct net_device *netdev, gfp_t gfp);
+
void
nl80211_send_cqm_pktloss_notify(struct cfg80211_registered_device *rdev,
struct net_device *netdev, const u8 *peer,
--
1.7.10.4
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PATCHv5 4/8] mac80211: add radar detection command/event
2012-12-13 13:58 [PATCHv5 0/8] Add DFS master ability Simon Wunderlich
` (2 preceding siblings ...)
2012-12-13 13:58 ` [PATCHv5 3/8] nl80211/cfg80211: add radar detection command/event Simon Wunderlich
@ 2012-12-13 13:58 ` Simon Wunderlich
2013-01-02 13:40 ` Johannes Berg
2012-12-13 13:58 ` [PATCHv5 5/8] mac80211: check radar interaction with scan and roc Simon Wunderlich
` (4 subsequent siblings)
8 siblings, 1 reply; 27+ messages in thread
From: Simon Wunderlich @ 2012-12-13 13:58 UTC (permalink / raw)
To: linux-wireless
Cc: johannes, victorg, linville, kgiori, zefir.kurtisi, adrian, j,
coelho, assaf, igalc, nbd, mathias.kretschmer, Simon Wunderlich
From: Victor Goldenshtein <victorg@ti.com>
Add command to trigger radar detection in the driver/FW.
Once radar detection is started it should continuously
monitor for radars as long as the channel active.
If radar is detected usermode notified with 'radar
detected' event.
Signed-off-by: Victor Goldenshtein <victorg@ti.com>
[rebase, change to chandef, minor fixes]
Signed-off-by: Simon Wunderlich <siwu@hrz.tu-chemnitz.de>
---
include/net/mac80211.h | 19 +++++++++++++++++++
net/mac80211/cfg.c | 28 +++++++++++++++++++++++++++
net/mac80211/driver-ops.h | 14 ++++++++++++++
net/mac80211/iface.c | 4 ++++
net/mac80211/mlme.c | 11 +++++++++++
net/mac80211/trace.h | 46 +++++++++++++++++++++++++++++++++++++++++++++
6 files changed, 122 insertions(+)
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index ee50c5e..b9186f4 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -2475,6 +2475,10 @@ enum ieee80211_rate_control_changed {
* @restart_complete: Called after a call to ieee80211_restart_hw(), when the
* reconfiguration has completed. This can help the driver implement the
* reconfiguration step. This callback may sleep.
+ *
+ * @start_radar_detection: Start radar detection on current operational
+ * channel, once started it will continuously monitor for radars as long
+ * as the channel active. This callback can sleep.
*/
struct ieee80211_ops {
void (*tx)(struct ieee80211_hw *hw,
@@ -2648,6 +2652,10 @@ struct ieee80211_ops {
struct ieee80211_chanctx_conf *ctx);
void (*restart_complete)(struct ieee80211_hw *hw);
+
+ int (*start_radar_detection)(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_channel *chan);
};
/**
@@ -3872,6 +3880,17 @@ void ieee80211_cqm_rssi_notify(struct ieee80211_vif *vif,
gfp_t gfp);
/**
+ * ieee80211_radar_detected - inform a configured connection that
+ * radar was detected on the current channel
+ *
+ * @vif: &struct ieee80211_vif pointer from the add_interface callback.
+ * @chan: radar detected on this channel.
+ * @gfp: context flags.
+ */
+void ieee80211_radar_detected(struct ieee80211_vif *vif,
+ struct ieee80211_channel *chan, gfp_t gfp);
+
+/**
* ieee80211_chswitch_done - Complete channel switch process
* @vif: &struct ieee80211_vif pointer from the add_interface callback.
* @success: make the channel switch successful or not
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 5c61677..a9de035 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -2551,6 +2551,33 @@ static int ieee80211_cancel_remain_on_channel(struct wiphy *wiphy,
return ieee80211_cancel_roc(local, cookie, false);
}
+static int ieee80211_start_radar_detection(struct wiphy *wiphy,
+ struct net_device *dev,
+ struct cfg80211_chan_def *chandef)
+{
+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+ struct ieee80211_local *local = sdata->local;
+ int res;
+
+ if (!local->ops->start_radar_detection)
+ return -EOPNOTSUPP;
+
+ /* whatever, but channel contexts should not complain about that one */
+ sdata->smps_mode = IEEE80211_SMPS_OFF;
+ sdata->needed_rx_chains = sdata->local->rx_chains;
+
+ /* TODO: shall we define SINGLE_ONLY context here too? */
+ if (ieee80211_vif_use_channel(sdata, chandef,
+ IEEE80211_CHANCTX_EXCLUSIVE))
+ return -EBUSY;
+
+ res = drv_start_radar_detection(local, sdata, chandef->chan);
+ if (!res)
+ ieee80211_vif_release_channel(sdata);
+
+ return res;
+}
+
static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
struct ieee80211_channel *chan, bool offchan,
unsigned int wait, const u8 *buf, size_t len,
@@ -3255,4 +3282,5 @@ struct cfg80211_ops mac80211_config_ops = {
.get_et_stats = ieee80211_get_et_stats,
.get_et_strings = ieee80211_get_et_strings,
.get_channel = ieee80211_cfg_get_channel,
+ .start_radar_detection = ieee80211_start_radar_detection,
};
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index c6560cc..f703dfc 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -323,6 +323,20 @@ static inline void drv_cancel_hw_scan(struct ieee80211_local *local,
trace_drv_return_void(local);
}
+static inline int drv_start_radar_detection(struct ieee80211_local *local,
+ struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_channel *chan)
+{
+ int ret;
+
+ might_sleep();
+
+ trace_drv_start_radar_detection(local, chan);
+ ret = local->ops->start_radar_detection(&local->hw, &sdata->vif, chan);
+ trace_drv_return_int(local, ret);
+ return ret;
+}
+
static inline int
drv_sched_scan_start(struct ieee80211_local *local,
struct ieee80211_sub_if_data *sdata,
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 09a80b5..2895cd8 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -829,6 +829,10 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
u.vlan.list)
dev_close(vlan->dev);
WARN_ON(!list_empty(&sdata->u.ap.vlans));
+
+ /* reset DFS channel availability check */
+ if (local->_oper_channel)
+ local->_oper_channel->cac_started = false;
} else if (sdata->vif.type == NL80211_IFTYPE_STATION) {
ieee80211_mgd_stop(sdata);
}
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 7753a9c..a734036 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -4056,3 +4056,14 @@ void ieee80211_cqm_rssi_notify(struct ieee80211_vif *vif,
cfg80211_cqm_rssi_notify(sdata->dev, rssi_event, gfp);
}
EXPORT_SYMBOL(ieee80211_cqm_rssi_notify);
+
+void ieee80211_radar_detected(struct ieee80211_vif *vif,
+ struct ieee80211_channel *chan, gfp_t gfp)
+{
+ struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
+
+ trace_api_radar_detected(sdata, chan->center_freq);
+
+ cfg80211_radar_detected(sdata->dev, chan, gfp);
+}
+EXPORT_SYMBOL(ieee80211_radar_detected);
diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h
index a8270b4..2c73982 100644
--- a/net/mac80211/trace.h
+++ b/net/mac80211/trace.h
@@ -1815,6 +1815,52 @@ TRACE_EVENT(stop_queue,
)
);
+TRACE_EVENT(api_radar_detected,
+ TP_PROTO(struct ieee80211_sub_if_data *sdata,
+ u16 center_freq),
+
+ TP_ARGS(sdata, center_freq),
+
+ TP_STRUCT__entry(
+ VIF_ENTRY
+ __field(u16, center_freq)
+ ),
+
+ TP_fast_assign(
+ VIF_ASSIGN;
+ __entry->center_freq = center_freq;
+ ),
+
+ TP_printk(
+ VIF_PR_FMT " radar on freq:%d",
+ VIF_PR_ARG, __entry->center_freq
+ )
+)
+
+TRACE_EVENT(drv_start_radar_detection,
+ TP_PROTO(struct ieee80211_local *local,
+ struct ieee80211_channel *chan),
+
+ TP_ARGS(local, chan),
+
+ TP_STRUCT__entry(
+ LOCAL_ENTRY
+ __field(u16, freq)
+ __field(int, cac_type)
+ ),
+
+ TP_fast_assign(
+ LOCAL_ASSIGN;
+ __entry->freq = chan->center_freq;
+ __entry->cac_type = chan->cac_type;
+ ),
+
+ TP_printk(
+ LOCAL_PR_FMT " start radar detection on freq:%u cac_type:%d",
+ LOCAL_PR_ARG, __entry->freq, __entry->cac_type
+ )
+);
+
#ifdef CONFIG_MAC80211_MESSAGE_TRACING
#undef TRACE_SYSTEM
#define TRACE_SYSTEM mac80211_msg
--
1.7.10.4
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PATCHv5 5/8] mac80211: check radar interaction with scan and roc
2012-12-13 13:58 [PATCHv5 0/8] Add DFS master ability Simon Wunderlich
` (3 preceding siblings ...)
2012-12-13 13:58 ` [PATCHv5 4/8] mac80211: " Simon Wunderlich
@ 2012-12-13 13:58 ` Simon Wunderlich
2012-12-13 13:58 ` [PATCHv5 6/8] nl80211/cfg80211: add ap channel switch command Simon Wunderlich
` (3 subsequent siblings)
8 siblings, 0 replies; 27+ messages in thread
From: Simon Wunderlich @ 2012-12-13 13:58 UTC (permalink / raw)
To: linux-wireless
Cc: johannes, victorg, linville, kgiori, zefir.kurtisi, adrian, j,
coelho, assaf, igalc, nbd, mathias.kretschmer, Simon Wunderlich
Scanning and remain on channel functionality must be disabled while
doing radar detection/scanning, and vice versa.
Signed-off-by: Simon Wunderlich <siwu@hrz.tu-chemnitz.de>
---
net/mac80211/cfg.c | 12 ++++++++++--
net/mac80211/ieee80211_i.h | 3 +++
net/mac80211/scan.c | 3 +++
3 files changed, 16 insertions(+), 2 deletions(-)
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index a9de035..9c190c5 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1019,6 +1019,7 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev)
skb_queue_purge(&sdata->u.ap.ps.bc_buf);
ieee80211_vif_release_channel(sdata);
+ local->radar_detect_enabled = false;
return 0;
}
@@ -2301,7 +2302,9 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local,
INIT_LIST_HEAD(&roc->dependents);
/* if there's one pending or we're scanning, queue this one */
- if (!list_empty(&local->roc_list) || local->scanning)
+ if (!list_empty(&local->roc_list) ||
+ local->scanning ||
+ local->radar_detect_enabled)
goto out_check_combine;
/* if not HW assist, just queue & schedule work */
@@ -2562,6 +2565,9 @@ static int ieee80211_start_radar_detection(struct wiphy *wiphy,
if (!local->ops->start_radar_detection)
return -EOPNOTSUPP;
+ if (!list_empty(&local->roc_list) || local->scanning)
+ return -EBUSY;
+
/* whatever, but channel contexts should not complain about that one */
sdata->smps_mode = IEEE80211_SMPS_OFF;
sdata->needed_rx_chains = sdata->local->rx_chains;
@@ -2572,8 +2578,10 @@ static int ieee80211_start_radar_detection(struct wiphy *wiphy,
return -EBUSY;
res = drv_start_radar_detection(local, sdata, chandef->chan);
- if (!res)
+ if (!res) {
+ local->radar_detect_enabled = true;
ieee80211_vif_release_channel(sdata);
+ }
return res;
}
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 42d0d02..abb2759 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -962,6 +962,9 @@ struct ieee80211_local {
/* wowlan is enabled -- don't reconfig on resume */
bool wowlan;
+ /* DFS/radar detection is enabled */
+ bool radar_detect_enabled;
+
/* number of RX chains the hardware has */
u8 rx_chains;
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index 8ed83dc..c058749 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -369,6 +369,9 @@ static int ieee80211_start_sw_scan(struct ieee80211_local *local)
static bool ieee80211_can_scan(struct ieee80211_local *local,
struct ieee80211_sub_if_data *sdata)
{
+ if (local->radar_detect_enabled)
+ return false;
+
if (!list_empty(&local->roc_list))
return false;
--
1.7.10.4
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PATCHv5 6/8] nl80211/cfg80211: add ap channel switch command
2012-12-13 13:58 [PATCHv5 0/8] Add DFS master ability Simon Wunderlich
` (4 preceding siblings ...)
2012-12-13 13:58 ` [PATCHv5 5/8] mac80211: check radar interaction with scan and roc Simon Wunderlich
@ 2012-12-13 13:58 ` Simon Wunderlich
2013-01-02 13:45 ` Johannes Berg
2012-12-13 13:58 ` [PATCHv5 7/8] mac80211: add ap channel switch command/event Simon Wunderlich
` (2 subsequent siblings)
8 siblings, 1 reply; 27+ messages in thread
From: Simon Wunderlich @ 2012-12-13 13:58 UTC (permalink / raw)
To: linux-wireless
Cc: johannes, victorg, linville, kgiori, zefir.kurtisi, adrian, j,
coelho, assaf, igalc, nbd, mathias.kretschmer, Simon Wunderlich
From: Victor Goldenshtein <victorg@ti.com>
Add NL80211_CMD_AP_CH_SWITCH command which
triggers an AP channel switch process.
Usermode notified about channel switch complete
event with NL80211_CMD_CH_SWITCH_NOTIFY.
Usermode (hostapd) is responsible to update the
channel switch announcement IE in the beacon
prior and after the channel switch operation.
Signed-off-by: Victor Goldenshtein <victorg@ti.com>
[Changes:
* change to chandef
* stop ap when moving to a DFS channel
* document channel switch new behaviour
* rebase on current master]
Signed-off-by: Simon Wunderlich <siwu@hrz.tu-chemnitz.de>
---
include/net/cfg80211.h | 38 +++++++++++++++++++++++-
include/uapi/linux/nl80211.h | 29 ++++++++++++++++++
net/wireless/mlme.c | 8 +++--
net/wireless/nl80211.c | 67 ++++++++++++++++++++++++++++++++++++++++--
net/wireless/nl80211.h | 3 +-
5 files changed, 139 insertions(+), 6 deletions(-)
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 3740b57..7cfa08d 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -331,6 +331,36 @@ struct cfg80211_chan_def {
};
/**
+ * struct ieee80211_ap_ch_switch - holds the ap channel switch data
+ *
+ * The information provided in this structure is required for the ap channel
+ * switch operation.
+ *
+ * @timestamp: value in microseconds of the 64-bit Time Synchronization
+ * Function (TSF) timer when the frame containing the channel switch
+ * announcement was received. This is simply the rx.mactime parameter
+ * the driver passed into mac80211.
+ * @block_tx: Indicates whether transmission must be blocked before the
+ * scheduled channel switch, setting this flag will rise Channel Switch
+ * Mode bit in the AP CSA IE which means that all STAs in a BSS shall
+ * stop transmitting immediately.
+ * @post_switch_block_tx: Indicates whether the AP transmission must be blocked
+ * after the scheduled channel switch, this should be set if the target
+ * channel is DFS channel.
+ * @chandef: the new channel to switch to
+ * @count: the number of TBTT's until the channel switch event
+ */
+struct ieee80211_ap_ch_switch {
+ u64 timestamp;
+ bool block_tx;
+ bool post_switch_block_tx;
+ struct cfg80211_chan_def chandef;
+ u8 count;
+};
+
+
+
+/**
* cfg80211_get_chandef_type - return old channel type from chandef
* @chandef: the channel definition
*
@@ -1773,6 +1803,7 @@ struct cfg80211_gtk_rekey_data {
* @stop_p2p_device: Stop the given P2P device.
*
* @start_radar_detection: Start radar detection in the driver.
+ * @ap_channel_switch: Perform AP channel switch.
*/
struct cfg80211_ops {
int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
@@ -1997,6 +2028,9 @@ struct cfg80211_ops {
int (*start_radar_detection)(struct wiphy *wiphy,
struct net_device *dev,
struct cfg80211_chan_def *chandef);
+ int (*ap_channel_switch)(struct wiphy *wiphy,
+ struct net_device *dev,
+ struct ieee80211_ap_ch_switch *ap_ch_sw);
};
/*
@@ -3723,11 +3757,13 @@ bool cfg80211_reg_can_beacon(struct wiphy *wiphy,
* cfg80211_ch_switch_notify - update wdev channel and notify userspace
* @dev: the device which switched channels
* @chandef: the new channel definition
+ * @stop_ap: stop the access point
*
* Acquires wdev_lock, so must only be called from sleepable driver context!
*/
void cfg80211_ch_switch_notify(struct net_device *dev,
- struct cfg80211_chan_def *chandef);
+ struct cfg80211_chan_def *chandef,
+ bool stop_ap);
/*
* cfg80211_tdls_oper_request - request userspace to perform TDLS operation
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 2303f86..7a98735 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -589,6 +589,21 @@
* @NL80211_CMD_RADAR_DETECT: Start radar detection in the driver/HW. Once
* radar detected usermode notified with this event.
*
+ * @NL80211_CMD_AP_CH_SWITCH: Perform a channel switch in the driver (for
+ * AP/GO). Userspace daemon is responsible to update the CSA IE in the
+ * beacon prior and after the channel switch operation. Userspace notified
+ * about channel switch complete event with %NL80211_CMD_CH_SWITCH_NOTIFY.
+ * %NL80211_ATTR_WIPHY_FREQ is used to specify the new channel frequency.
+ * %NL80211_ATTR_CH_SWITCH_BLOCK_TX is used to specify that tx must be
+ * blocked on the current channel. %NL80211_ATTR_CH_SWITCH_POST_BLOCK_TX
+ * is used to specify that tx must be blocked on the target channel.
+ * %NL80211_FREQ_ATTR_CH_SWITCH_COUNT to specify the number of TBTT's until
+ * the device switches to the target channel.
+ * If the target channel is a DFS channel, the AP will be stopped (stop_ap)
+ * and NL80211_ATTR_CH_SWITCH_POST_BLOCK_TX will be sent back with the
+ * %NL80211_CMD_CH_SWITCH_NOTIFY event to reflect this. Userspace may then
+ * start another Channel Availability Check (CAC) to use the new channel.
+ *
* @NL80211_CMD_MAX: highest used command number
* @__NL80211_CMD_AFTER_LAST: internal use
*/
@@ -740,6 +755,7 @@ enum nl80211_commands {
NL80211_CMD_SET_MCAST_RATE,
NL80211_CMD_RADAR_DETECT,
+ NL80211_CMD_AP_CH_SWITCH,
/* add new commands above here */
@@ -1314,6 +1330,14 @@ enum nl80211_commands {
* START_AP and SET_BSS commands. This can have the values 0 or 1;
* if not given in START_AP 0 is assumed, if not given in SET_BSS
* no change is made.
+ * @NL80211_ATTR_CH_SWITCH_COUNT: u32 attribute specifying the number of TBTT's
+ * until the channel switch event.
+ * @NL80211_ATTR_CH_SWITCH_BLOCK_TX: flag attribute specifying that transmission
+ * must be blocked on the current channel (before the channel switch
+ * operation).
+ * @NL80211_ATTR_CH_SWITCH_POST_BLOCK_TX: flag attribute specifying that
+ * transmission must be blocked on the target channel after the channel
+ * switch operation, should be set if the target channel is DFS channel.
*
* @NL80211_ATTR_MAX: highest attribute number currently defined
* @__NL80211_ATTR_AFTER_LAST: internal use
@@ -1585,6 +1609,10 @@ enum nl80211_attrs {
NL80211_ATTR_P2P_CTWINDOW,
NL80211_ATTR_P2P_OPPPS,
+ NL80211_ATTR_CH_SWITCH_COUNT,
+ NL80211_ATTR_CH_SWITCH_BLOCK_TX,
+ NL80211_ATTR_CH_SWITCH_POST_BLOCK_TX,
+
/* add attributes here, update the policy in nl80211.c */
__NL80211_ATTR_AFTER_LAST,
@@ -3165,6 +3193,7 @@ enum nl80211_feature_flags {
NL80211_FEATURE_P2P_GO_CTWIN = 1 << 11,
NL80211_FEATURE_P2P_GO_OPPPS = 1 << 12,
NL80211_FEATURE_20MHZ_DFS = 1 << 13,
+ NL80211_FEATURE_AP_CH_SWITCH = 1 << 14,
};
/**
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
index 02666e3..8cdbdd0e 100644
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
@@ -989,7 +989,8 @@ void cfg80211_pmksa_candidate_notify(struct net_device *dev, int index,
EXPORT_SYMBOL(cfg80211_pmksa_candidate_notify);
void cfg80211_ch_switch_notify(struct net_device *dev,
- struct cfg80211_chan_def *chandef)
+ struct cfg80211_chan_def *chandef,
+ bool stop_ap)
{
struct wireless_dev *wdev = dev->ieee80211_ptr;
struct wiphy *wiphy = wdev->wiphy;
@@ -997,6 +998,9 @@ void cfg80211_ch_switch_notify(struct net_device *dev,
trace_cfg80211_ch_switch_notify(dev, chandef);
+ if (stop_ap)
+ cfg80211_stop_ap(rdev, dev);
+
wdev_lock(wdev);
if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP &&
@@ -1004,7 +1008,7 @@ void cfg80211_ch_switch_notify(struct net_device *dev,
goto out;
wdev->channel = chandef->chan;
- nl80211_ch_switch_notify(rdev, dev, chandef, GFP_KERNEL);
+ nl80211_ch_switch_notify(rdev, dev, chandef, stop_ap, GFP_KERNEL);
out:
wdev_unlock(wdev);
return;
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index d49c0c2..898d829 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -365,6 +365,9 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
[NL80211_ATTR_SCAN_FLAGS] = { .type = NLA_U32 },
[NL80211_ATTR_P2P_CTWINDOW] = { .type = NLA_U8 },
[NL80211_ATTR_P2P_OPPPS] = { .type = NLA_U8 },
+ [NL80211_ATTR_CH_SWITCH_COUNT] = { .type = NLA_U32 },
+ [NL80211_ATTR_CH_SWITCH_BLOCK_TX] = { .type = NLA_FLAG },
+ [NL80211_ATTR_CH_SWITCH_POST_BLOCK_TX] = { .type = NLA_FLAG },
};
/* policy for the key attributes */
@@ -4811,7 +4814,8 @@ static int nl80211_start_radar_detection(struct sk_buff *skb,
struct cfg80211_chan_def chandef;
int err;
- if (!(rdev->wiphy.features & NL80211_FEATURE_20MHZ_DFS))
+ if (!(rdev->wiphy.features & NL80211_FEATURE_20MHZ_DFS) ||
+ !(rdev->wiphy.features & NL80211_FEATURE_AP_CH_SWITCH))
return -EOPNOTSUPP;
err = nl80211_parse_chandef(rdev, info, &chandef);
@@ -4853,6 +4857,51 @@ static int nl80211_start_radar_detection(struct sk_buff *skb,
return err;
}
+static int nl80211_ap_channel_switch(struct sk_buff *skb,
+ struct genl_info *info)
+{
+ struct cfg80211_registered_device *rdev = info->user_ptr[0];
+ struct net_device *dev = info->user_ptr[1];
+ struct ieee80211_ap_ch_switch ap_ch_sw;
+ int err;
+
+ if (!rdev->ops->ap_channel_switch)
+ return -EOPNOTSUPP;
+
+ if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
+ dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
+ return -EOPNOTSUPP;
+
+ if (!info->attrs[NL80211_ATTR_CH_SWITCH_COUNT] ||
+ !info->attrs[NL80211_ATTR_WIPHY_FREQ] ||
+ !info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE])
+ return -EINVAL;
+
+ memset(&ap_ch_sw, 0, sizeof(ap_ch_sw));
+
+ err = nl80211_parse_chandef(rdev, info, &ap_ch_sw.chandef);
+ if (err)
+ return err;
+
+ /* DFS is currently supported for 20 MHz only. */
+ if (ap_ch_sw.chandef.width > NL80211_CHAN_WIDTH_20)
+ return -EOPNOTSUPP;
+
+ if (!ap_ch_sw.chandef.chan ||
+ ap_ch_sw.chandef.chan->flags & IEEE80211_CHAN_DISABLED)
+ return -EINVAL;
+
+ ap_ch_sw.count = nla_get_u32(info->attrs[NL80211_ATTR_CH_SWITCH_COUNT]);
+
+ if (info->attrs[NL80211_ATTR_CH_SWITCH_BLOCK_TX])
+ ap_ch_sw.block_tx = true;
+
+ if (info->attrs[NL80211_ATTR_CH_SWITCH_POST_BLOCK_TX])
+ ap_ch_sw.post_switch_block_tx = true;
+
+ return rdev->ops->ap_channel_switch(&rdev->wiphy, dev, &ap_ch_sw);
+}
+
static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb,
u32 seq, int flags,
struct cfg80211_registered_device *rdev,
@@ -7844,6 +7893,14 @@ static struct genl_ops nl80211_ops[] = {
.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
NL80211_FLAG_NEED_RTNL,
},
+ {
+ .cmd = NL80211_CMD_AP_CH_SWITCH,
+ .doit = nl80211_ap_channel_switch,
+ .policy = nl80211_policy,
+ .flags = GENL_ADMIN_PERM,
+ .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
+ NL80211_FLAG_NEED_RTNL,
+ },
};
static struct genl_multicast_group nl80211_mlme_mcgrp = {
@@ -8958,7 +9015,8 @@ void nl80211_pmksa_candidate_notify(struct cfg80211_registered_device *rdev,
void nl80211_ch_switch_notify(struct cfg80211_registered_device *rdev,
struct net_device *netdev,
- struct cfg80211_chan_def *chandef, gfp_t gfp)
+ struct cfg80211_chan_def *chandef,
+ bool ap_stopped, gfp_t gfp)
{
struct sk_buff *msg;
void *hdr;
@@ -8979,6 +9037,11 @@ void nl80211_ch_switch_notify(struct cfg80211_registered_device *rdev,
if (nl80211_send_chandef(msg, chandef))
goto nla_put_failure;
+ if (ap_stopped &&
+ nla_put_flag(msg, NL80211_ATTR_CH_SWITCH_POST_BLOCK_TX))
+ goto nla_put_failure;
+
+
genlmsg_end(msg, hdr);
genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
diff --git a/net/wireless/nl80211.h b/net/wireless/nl80211.h
index 28b9a34..68ac459 100644
--- a/net/wireless/nl80211.h
+++ b/net/wireless/nl80211.h
@@ -134,7 +134,8 @@ void nl80211_pmksa_candidate_notify(struct cfg80211_registered_device *rdev,
void nl80211_ch_switch_notify(struct cfg80211_registered_device *rdev,
struct net_device *dev,
- struct cfg80211_chan_def *chandef, gfp_t gfp);
+ struct cfg80211_chan_def *chandef,
+ bool ap_stopped, gfp_t gfp);
bool nl80211_unexpected_frame(struct net_device *dev,
const u8 *addr, gfp_t gfp);
--
1.7.10.4
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PATCHv5 7/8] mac80211: add ap channel switch command/event
2012-12-13 13:58 [PATCHv5 0/8] Add DFS master ability Simon Wunderlich
` (5 preceding siblings ...)
2012-12-13 13:58 ` [PATCHv5 6/8] nl80211/cfg80211: add ap channel switch command Simon Wunderlich
@ 2012-12-13 13:58 ` Simon Wunderlich
2013-01-02 13:46 ` Johannes Berg
2013-01-02 13:47 ` Johannes Berg
2012-12-13 13:58 ` [PATCHv5 8/8] nl80211: allow DFS in start_ap Simon Wunderlich
2013-01-02 13:53 ` [PATCHv5 0/8] Add DFS master ability Johannes Berg
8 siblings, 2 replies; 27+ messages in thread
From: Simon Wunderlich @ 2012-12-13 13:58 UTC (permalink / raw)
To: linux-wireless
Cc: johannes, victorg, linville, kgiori, zefir.kurtisi, adrian, j,
coelho, assaf, igalc, nbd, mathias.kretschmer, Simon Wunderlich
From: Victor Goldenshtein <victorg@ti.com>
Add ieee80211_ap_process_chanswitch(), to handle a channel switch
request for AP.
Add ieee80211_ap_ch_switch_done() which updates oper_channel
and notifies upper layers about channel switch complete event.
Signed-off-by: Victor Goldenshtein <victorg@ti.com>
[changes:
* change to chandef
* fix channel switch notify
* document ap_channel_switch()
* stop AP
* rebased on latest master]
Signed-off-by: Simon Wunderlich <siwu@hrz.tu-chemnitz.de>
---
include/net/mac80211.h | 27 ++++++++++++++++
net/mac80211/cfg.c | 27 ++++++++++++++++
net/mac80211/driver-ops.h | 12 +++++++
net/mac80211/ieee80211_i.h | 4 +++
net/mac80211/iface.c | 2 ++
net/mac80211/main.c | 2 ++
net/mac80211/mlme.c | 66 ++++++++++++++++++++++++++++++++++++++
net/mac80211/trace.h | 75 ++++++++++++++++++++++++++++++++++++++++++++
8 files changed, 215 insertions(+)
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index b9186f4..a7b17cf 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -2358,6 +2358,13 @@ enum ieee80211_rate_control_changed {
* callback. They must then call ieee80211_chswitch_done() to indicate
* completion of the channel switch.
*
+ * @ap_channel_switch: Announce a channel switch in the beacons according to the
+ * parameters passed. The driver must add the CSA IE in the beacon and
+ * decrement the TBTT with each beacon sent (for details, see
+ * IEEE 802.11-2012 8.4.2.21). The CSA IE must be set in the beacon before
+ * calling this function. After completion, ieee80211_ap_ch_switch_done()
+ * must be called by the driver to finalize the switch.
+ *
* @napi_poll: Poll Rx queue for incoming data frames.
*
* @set_antenna: Set antenna configuration (tx_ant, rx_ant) on the device.
@@ -2594,6 +2601,8 @@ struct ieee80211_ops {
void (*flush)(struct ieee80211_hw *hw, bool drop);
void (*channel_switch)(struct ieee80211_hw *hw,
struct ieee80211_channel_switch *ch_switch);
+ int (*ap_channel_switch)(struct ieee80211_hw *hw,
+ struct ieee80211_ap_ch_switch *ap_ch_switch);
int (*napi_poll)(struct ieee80211_hw *hw, int budget);
int (*set_antenna)(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant);
int (*get_antenna)(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant);
@@ -3891,6 +3900,24 @@ void ieee80211_radar_detected(struct ieee80211_vif *vif,
struct ieee80211_channel *chan, gfp_t gfp);
/**
+ * ieee80211_ap_ch_switch_done_work - ap channel switch complete work.
+ *
+ * @work: the channel switch complete work
+ */
+void ieee80211_ap_ch_switch_work(struct work_struct *work);
+
+/**
+ * ieee80211_ap_ch_switch_done - inform and update a configured connection
+ * that channel switch is complete.
+ *
+ * @vif: &struct ieee80211_vif pointer from the add_interface callback.
+ * @new_channel: the new channel.
+ * @type: new channe ltype.
+ */
+void ieee80211_ap_ch_switch_done(struct ieee80211_vif *vif,
+ struct cfg80211_chan_def *chandef);
+
+/**
* ieee80211_chswitch_done - Complete channel switch process
* @vif: &struct ieee80211_vif pointer from the add_interface callback.
* @success: make the channel switch successful or not
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 9c190c5..394b989 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -2586,6 +2586,32 @@ static int ieee80211_start_radar_detection(struct wiphy *wiphy,
return res;
}
+static int
+ieee80211_ap_process_chanswitch(struct wiphy *wiphy,
+ struct net_device *dev,
+ struct ieee80211_ap_ch_switch *ap_ch_switch)
+{
+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+ struct ieee80211_local *local = sdata->local;
+
+ if (!local->ops->ap_channel_switch)
+ return -EOPNOTSUPP;
+
+ if (!ap_ch_switch || !ap_ch_switch->chandef.chan)
+ return -EINVAL;
+
+ if (local->ap_cs_chandef.chan)
+ return -EBUSY;
+
+ local->ap_cs_chandef = ap_ch_switch->chandef;
+
+ ieee80211_stop_queues_by_reason(&local->hw,
+ IEEE80211_QUEUE_STOP_REASON_CH_SW);
+
+ drv_ap_channel_switch(local, ap_ch_switch);
+ return 0;
+}
+
static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
struct ieee80211_channel *chan, bool offchan,
unsigned int wait, const u8 *buf, size_t len,
@@ -3291,4 +3317,5 @@ struct cfg80211_ops mac80211_config_ops = {
.get_et_strings = ieee80211_get_et_strings,
.get_channel = ieee80211_cfg_get_channel,
.start_radar_detection = ieee80211_start_radar_detection,
+ .ap_channel_switch = ieee80211_ap_process_chanswitch,
};
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index f703dfc..4a2f17d 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -726,6 +726,18 @@ static inline void drv_channel_switch(struct ieee80211_local *local,
trace_drv_return_void(local);
}
+static inline int
+drv_ap_channel_switch(struct ieee80211_local *local,
+ struct ieee80211_ap_ch_switch *ap_ch_switch)
+{
+ int ret = -EOPNOTSUPP;
+ might_sleep();
+ trace_drv_ap_channel_switch(local, ap_ch_switch);
+ if (local->ops->ap_channel_switch)
+ ret = local->ops->ap_channel_switch(&local->hw, ap_ch_switch);
+ trace_drv_return_int(local, ret);
+ return ret;
+}
static inline int drv_set_antenna(struct ieee80211_local *local,
u32 tx_ant, u32 rx_ant)
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index abb2759..3d1938e 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -302,6 +302,7 @@ struct ieee80211_if_ap {
struct ps_data ps;
atomic_t num_mcast_sta; /* number of stations receiving multicast */
+ struct work_struct ap_ch_sw_work;
};
struct ieee80211_if_wds {
@@ -830,6 +831,7 @@ enum queue_stop_reason {
IEEE80211_QUEUE_STOP_REASON_AGGREGATION,
IEEE80211_QUEUE_STOP_REASON_SUSPEND,
IEEE80211_QUEUE_STOP_REASON_SKB_ADD,
+ IEEE80211_QUEUE_STOP_REASON_CH_SW,
};
#ifdef CONFIG_MAC80211_LEDS
@@ -1051,6 +1053,8 @@ struct ieee80211_local {
struct ieee80211_channel *_oper_channel;
enum nl80211_channel_type _oper_channel_type;
+ struct cfg80211_chan_def ap_cs_chandef;
+
/* Temporary remain-on-channel for off-channel operations */
struct ieee80211_channel *tmp_channel;
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 2895cd8..d5c7603 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -1237,6 +1237,8 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata,
case NL80211_IFTYPE_AP:
skb_queue_head_init(&sdata->u.ap.ps.bc_buf);
INIT_LIST_HEAD(&sdata->u.ap.vlans);
+ INIT_WORK(&sdata->u.ap.ap_ch_sw_work,
+ ieee80211_ap_ch_switch_work);
break;
case NL80211_IFTYPE_P2P_CLIENT:
type = NL80211_IFTYPE_STATION;
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 1b087ff..efa3eef 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -612,6 +612,8 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
wiphy->features |= NL80211_FEATURE_LOW_PRIORITY_SCAN |
NL80211_FEATURE_AP_SCAN;
+ if (ops->ap_channel_switch)
+ wiphy->features |= NL80211_FEATURE_AP_CH_SWITCH;
if (!ops->set_key)
wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index a734036..8966627 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -4067,3 +4067,69 @@ void ieee80211_radar_detected(struct ieee80211_vif *vif,
cfg80211_radar_detected(sdata->dev, chan, gfp);
}
EXPORT_SYMBOL(ieee80211_radar_detected);
+
+void ieee80211_ap_ch_switch_work(struct work_struct *work)
+{
+ struct ieee80211_sub_if_data *sdata =
+ container_of(work, struct ieee80211_sub_if_data,
+ u.ap.ap_ch_sw_work);
+ struct ieee80211_local *local = sdata->local;
+ bool stop_ap = false;
+
+ /* announce where we are now. */
+ if (!local->ap_cs_chandef.chan)
+ goto announce;
+
+ mutex_lock(&local->mtx);
+ if (local->ap_cs_chandef.chan->flags & IEEE80211_CHAN_RADAR) {
+ sdata_info(sdata, "changing to DFS channel\n");
+ /* when changing to a DFS channel, stop AP. Userspace must
+ * restart AP or do start radar detection first.
+ */
+ stop_ap = true;
+ } else {
+ /* update the device channel directly */
+ sdata_info(sdata, "changing to non-DFS channel\n");
+
+ /* TODO: _oper_channel is deprecated ... use
+ * vif_release/use_channel instead? In this case, we must make
+ * sure that interface is down first ...
+ */
+ local->_oper_channel = local->ap_cs_chandef.chan;
+ local->hw.conf.channel = local->ap_cs_chandef.chan;
+ local->_oper_channel_type =
+ cfg80211_get_chandef_type(&local->ap_cs_chandef);
+ ieee80211_hw_config(sdata->local,
+ IEEE80211_CONF_CHANGE_CHANNEL);
+ ieee80211_wake_queues_by_reason(&local->hw,
+ IEEE80211_QUEUE_STOP_REASON_CH_SW);
+
+ }
+
+ sdata->vif.bss_conf.chandef = local->ap_cs_chandef;
+ local->ap_cs_chandef.chan = NULL;
+
+ mutex_unlock(&local->mtx);
+
+ announce:
+ cfg80211_ch_switch_notify(sdata->dev, &sdata->vif.bss_conf.chandef,
+ stop_ap);
+}
+
+void ieee80211_ap_ch_switch_done(struct ieee80211_vif *vif,
+ struct cfg80211_chan_def *new_chandef)
+{
+ struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
+ struct ieee80211_local *local = sdata->local;
+
+ if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_AP))
+ return;
+
+ if (WARN_ON(!cfg80211_chandef_identical(&local->ap_cs_chandef,
+ new_chandef)))
+ return;
+
+ trace_api_ap_ch_switch_done(sdata, new_chandef);
+ schedule_work(&sdata->u.ap.ap_ch_sw_work);
+}
+EXPORT_SYMBOL(ieee80211_ap_ch_switch_done);
diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h
index 2c73982..6264b43 100644
--- a/net/mac80211/trace.h
+++ b/net/mac80211/trace.h
@@ -45,6 +45,35 @@
__entry->center_freq1, __entry->center_freq2, \
__entry->rx_chains_static, __entry->rx_chains_dynamic
+#define CHAN_DEF_ENTRY __field(enum ieee80211_band, band) \
+ __field(u32, control_freq) \
+ __field(u32, width) \
+ __field(u32, center_freq1) \
+ __field(u32, center_freq2)
+#define CHAN_DEF_ASSIGN(chandef) \
+ do { \
+ if ((chandef) && (chandef)->chan) { \
+ __entry->band = (chandef)->chan->band; \
+ __entry->control_freq = \
+ (chandef)->chan->center_freq; \
+ __entry->width = (chandef)->width; \
+ __entry->center_freq1 = (chandef)->center_freq1;\
+ __entry->center_freq2 = (chandef)->center_freq2;\
+ } else { \
+ __entry->band = 0; \
+ __entry->control_freq = 0; \
+ __entry->width = 0; \
+ __entry->center_freq1 = 0; \
+ __entry->center_freq2 = 0; \
+ } \
+ } while (0)
+#define CHAN_DEF_PR_FMT \
+ "band: %d, control freq: %u, width: %d, cf1: %u, cf2: %u"
+#define CHAN_DEF_PR_ARG __entry->band, __entry->control_freq, \
+ __entry->width, __entry->center_freq1, \
+ __entry->center_freq2
+
+
/*
@@ -1861,6 +1890,52 @@ TRACE_EVENT(drv_start_radar_detection,
)
);
+TRACE_EVENT(drv_ap_channel_switch,
+ TP_PROTO(struct ieee80211_local *local,
+ struct ieee80211_ap_ch_switch *ap_ch_switch),
+
+ TP_ARGS(local, ap_ch_switch),
+
+ TP_STRUCT__entry(
+ LOCAL_ENTRY
+ CHAN_DEF_ENTRY
+ __field(u8, count)
+ ),
+
+ TP_fast_assign(
+ LOCAL_ASSIGN;
+ CHAN_DEF_ASSIGN(&ap_ch_switch->chandef);
+ __entry->count = ap_ch_switch->count;
+ ),
+
+ TP_printk(
+ LOCAL_PR_FMT " switching to :" CHAN_DEF_PR_FMT " count:%d",
+ LOCAL_PR_ARG, CHAN_DEF_PR_ARG, __entry->count
+ )
+);
+
+TRACE_EVENT(api_ap_ch_switch_done,
+ TP_PROTO(struct ieee80211_sub_if_data *sdata,
+ struct cfg80211_chan_def *chandef),
+
+ TP_ARGS(sdata, chandef),
+
+ TP_STRUCT__entry(
+ VIF_ENTRY
+ CHAN_DEF_ENTRY
+ ),
+
+ TP_fast_assign(
+ VIF_ASSIGN;
+ CHAN_DEF_ASSIGN(chandef);
+ ),
+
+ TP_printk(
+ VIF_PR_FMT ", " CHAN_DEF_PR_FMT,
+ VIF_PR_ARG, CHAN_DEF_PR_ARG
+ )
+)
+
#ifdef CONFIG_MAC80211_MESSAGE_TRACING
#undef TRACE_SYSTEM
#define TRACE_SYSTEM mac80211_msg
--
1.7.10.4
^ permalink raw reply related [flat|nested] 27+ messages in thread
* [PATCHv5 8/8] nl80211: allow DFS in start_ap
2012-12-13 13:58 [PATCHv5 0/8] Add DFS master ability Simon Wunderlich
` (6 preceding siblings ...)
2012-12-13 13:58 ` [PATCHv5 7/8] mac80211: add ap channel switch command/event Simon Wunderlich
@ 2012-12-13 13:58 ` Simon Wunderlich
2013-01-02 13:53 ` [PATCHv5 0/8] Add DFS master ability Johannes Berg
8 siblings, 0 replies; 27+ messages in thread
From: Simon Wunderlich @ 2012-12-13 13:58 UTC (permalink / raw)
To: linux-wireless
Cc: johannes, victorg, linville, kgiori, zefir.kurtisi, adrian, j,
coelho, assaf, igalc, nbd, mathias.kretschmer, Simon Wunderlich
This patch enables DFS within nl80211/cfg80211. start_ap now checks if
DFS is allowed on the channel, and enables it with SINGLE_ONLY channel
mode if appropriate.
Signed-off-by: Simon Wunderlich <siwu@hrz.tu-chemnitz.de>
---
net/wireless/chan.c | 5 ++++-
net/wireless/mlme.c | 11 +++++++++++
net/wireless/nl80211.c | 28 ++++++++++++++++++++++++++--
3 files changed, 41 insertions(+), 3 deletions(-)
diff --git a/net/wireless/chan.c b/net/wireless/chan.c
index 18888f6..16a5f69 100644
--- a/net/wireless/chan.c
+++ b/net/wireless/chan.c
@@ -344,7 +344,10 @@ cfg80211_get_chan_state(struct wireless_dev *wdev,
break;
case NL80211_IFTYPE_AP:
case NL80211_IFTYPE_P2P_GO:
- if (wdev->beacon_interval) {
+ if (wdev->dfs_nlportid) {
+ *chan = wdev->channel;
+ *chanmode = CHAN_MODE_SINGLE_ONLY;
+ } else if (wdev->beacon_interval) {
*chan = wdev->channel;
*chanmode = CHAN_MODE_SHARED;
}
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
index 8cdbdd0e..fec3414 100644
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
@@ -709,6 +709,7 @@ int cfg80211_mlme_register_mgmt(struct wireless_dev *wdev, u32 snd_portid,
void cfg80211_mlme_unregister_socket(struct wireless_dev *wdev, u32 nlportid)
{
struct wiphy *wiphy = wdev->wiphy;
+ struct net_device *dev = wdev->netdev;
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
struct cfg80211_mgmt_registration *reg, *tmp;
@@ -733,6 +734,16 @@ void cfg80211_mlme_unregister_socket(struct wireless_dev *wdev, u32 nlportid)
if (nlportid == wdev->ap_unexpected_nlportid)
wdev->ap_unexpected_nlportid = 0;
+
+ if (nlportid == wdev->dfs_nlportid) {
+ if ((dev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP ||
+ dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) &&
+ wdev->beacon_interval)
+ /* DFS userspace controller crashed, stop AP */
+ cfg80211_stop_ap(rdev, dev);
+
+ wdev->dfs_nlportid = 0;
+ }
}
void cfg80211_mlme_purge_registrations(struct wireless_dev *wdev)
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 898d829..2af9c6e 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -2600,6 +2600,9 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
struct net_device *dev = info->user_ptr[1];
struct wireless_dev *wdev = dev->ieee80211_ptr;
struct cfg80211_ap_settings params;
+ enum nl80211_chan_width dfs_capability = -1;
+ enum cfg80211_chan_mode chanmode;
+ struct ieee80211_channel *chan;
int err;
if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
@@ -2716,13 +2719,34 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
} else if (!nl80211_get_ap_channel(rdev, ¶ms))
return -EINVAL;
+ if (rdev->wiphy.features & NL80211_FEATURE_20MHZ_DFS &&
+ rdev->wiphy.features & NL80211_FEATURE_AP_CH_SWITCH)
+ dfs_capability = NL80211_CHAN_WIDTH_20;
+
if (!cfg80211_reg_can_beacon(&rdev->wiphy, ¶ms.chandef,
- -1))
+ dfs_capability))
return -EINVAL;
+ chan = params.chandef.chan;
+
+ if (chan->flags & IEEE80211_CHAN_RADAR) {
+ if (!wdev->dfs_nlportid)
+ return -EPERM;
+
+ if (!chan->cac_started)
+ return -EPERM;
+
+ if (time_is_after_jiffies(chan->radar_detect_timeout))
+ return -EPERM;
+
+ chanmode = CHAN_MODE_SINGLE_ONLY;
+ } else {
+ chanmode = CHAN_MODE_SHARED;
+ }
+
mutex_lock(&rdev->devlist_mtx);
err = cfg80211_can_use_chan(rdev, wdev, params.chandef.chan,
- CHAN_MODE_SHARED);
+ chanmode);
mutex_unlock(&rdev->devlist_mtx);
if (err)
--
1.7.10.4
^ permalink raw reply related [flat|nested] 27+ messages in thread
* Re: [PATCHv5 1/8] cfg80211: add CHAN_MODE_SINGLE_ONLY for DFS use
2012-12-13 13:58 ` [PATCHv5 1/8] cfg80211: add CHAN_MODE_SINGLE_ONLY for DFS use Simon Wunderlich
@ 2013-01-02 13:34 ` Johannes Berg
0 siblings, 0 replies; 27+ messages in thread
From: Johannes Berg @ 2013-01-02 13:34 UTC (permalink / raw)
To: Simon Wunderlich
Cc: linux-wireless, victorg, linville, kgiori, zefir.kurtisi, adrian,
j, coelho, assaf, igalc, nbd, mathias.kretschmer,
Simon Wunderlich
On Thu, 2012-12-13 at 14:58 +0100, Simon Wunderlich wrote:
> In DFS, we don't allow multiple virtual interfaces on one phy
> for now, because synchronizing channel state between them is not
> trivial and not implemented so far. Therefore, add another channel
> mode to seperate this.
The code looks fine, but the description is a bit wrong: this doesn't
disallow multiple virtual interfaces, just multiple channel contexts.
johannes
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCHv5 2/8] cfg/mac80211: add dfs capability to cfg80211_reg_can_beacon()
2012-12-13 13:58 ` [PATCHv5 2/8] cfg/mac80211: add dfs capability to cfg80211_reg_can_beacon() Simon Wunderlich
@ 2013-01-02 13:36 ` Johannes Berg
2013-01-02 14:45 ` Simon Wunderlich
0 siblings, 1 reply; 27+ messages in thread
From: Johannes Berg @ 2013-01-02 13:36 UTC (permalink / raw)
To: Simon Wunderlich
Cc: linux-wireless, victorg, linville, kgiori, zefir.kurtisi, adrian,
j, coelho, assaf, igalc, nbd, mathias.kretschmer,
Simon Wunderlich
On Thu, 2012-12-13 at 14:58 +0100, Simon Wunderlich wrote:
> * @chandef: the channel definition
> + * @dfs_capab: supported DFS bandwidth
> *
> * This function returns true if there is no secondary channel or the secondary
> * channel(s) can be used for beaconing (i.e. is not a radar channel etc.)
> */
> bool cfg80211_reg_can_beacon(struct wiphy *wiphy,
> - struct cfg80211_chan_def *chandef);
> + struct cfg80211_chan_def *chandef,
> + enum nl80211_chan_width dfs_capab);
Hm how does that make sense? The chandef contains a width? It seems like
the check whether or not DFS is supported (should be a bitfield btw)
should be outside of this function?
johannes
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCHv5 3/8] nl80211/cfg80211: add radar detection command/event
2012-12-13 13:58 ` [PATCHv5 3/8] nl80211/cfg80211: add radar detection command/event Simon Wunderlich
@ 2013-01-02 13:39 ` Johannes Berg
2013-01-03 7:35 ` Simon Wunderlich
0 siblings, 1 reply; 27+ messages in thread
From: Johannes Berg @ 2013-01-02 13:39 UTC (permalink / raw)
To: Simon Wunderlich
Cc: linux-wireless, victorg, linville, kgiori, zefir.kurtisi, adrian,
j, coelho, assaf, igalc, nbd, mathias.kretschmer,
Simon Wunderlich
On Thu, 2012-12-13 at 14:58 +0100, Simon Wunderlich wrote:
> +++ b/include/net/cfg80211.h
> @@ -133,6 +133,11 @@ enum ieee80211_channel_flags {
> * to enable this, this is useful only on 5 GHz band.
> * @orig_mag: internal use
> * @orig_mpwr: internal use
> + * @radar_detect_timeout: this timeout indicates the end of the channel
> + * availability check for radar channels (in jiffies), only after this
> + * period the user may initiate the tx on the channel.
> + * @cac_type: indicates that channel availability check is started for this
> + * channel type.
> */
> struct ieee80211_channel {
> enum ieee80211_band band;
> @@ -145,6 +150,9 @@ struct ieee80211_channel {
> bool beacon_found;
> u32 orig_flags;
> int orig_mag, orig_mpwr;
> + unsigned long radar_detect_timeout;
> + enum nl80211_channel_type cac_type;
> + bool cac_started;
Since we lock a channel, all of these should probably move to the
rdev/wiphy struct, I think.
And then the code checking channel contexts needs to be extended to not
allow another while a channel context is in use:
> + mutex_lock(&rdev->devlist_mtx);
> + err = cfg80211_can_use_chan(rdev, wdev, chandef.chan,
> + CHAN_MODE_SINGLE_ONLY);
> + mutex_unlock(&rdev->devlist_mtx);
This only does a spot check, keeping state needs to be handled
separately.
johannes
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCHv5 4/8] mac80211: add radar detection command/event
2012-12-13 13:58 ` [PATCHv5 4/8] mac80211: " Simon Wunderlich
@ 2013-01-02 13:40 ` Johannes Berg
2013-01-03 7:36 ` Simon Wunderlich
0 siblings, 1 reply; 27+ messages in thread
From: Johannes Berg @ 2013-01-02 13:40 UTC (permalink / raw)
To: Simon Wunderlich
Cc: linux-wireless, victorg, linville, kgiori, zefir.kurtisi, adrian,
j, coelho, assaf, igalc, nbd, mathias.kretschmer,
Simon Wunderlich
On Thu, 2012-12-13 at 14:58 +0100, Simon Wunderlich wrote:
> + int (*start_radar_detection)(struct ieee80211_hw *hw,
> + struct ieee80211_vif *vif,
> + struct ieee80211_channel *chan);
pass a chandef?
> +void ieee80211_radar_detected(struct ieee80211_vif *vif,
> + struct ieee80211_channel *chan, gfp_t gfp);
Here you probably don't need to pass the channel, once the tracking in
cfg80211 moves into the sdata (or even local) struct the same can happen
in mac80211.
johannes
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCHv5 6/8] nl80211/cfg80211: add ap channel switch command
2012-12-13 13:58 ` [PATCHv5 6/8] nl80211/cfg80211: add ap channel switch command Simon Wunderlich
@ 2013-01-02 13:45 ` Johannes Berg
2013-01-02 15:05 ` Simon Wunderlich
0 siblings, 1 reply; 27+ messages in thread
From: Johannes Berg @ 2013-01-02 13:45 UTC (permalink / raw)
To: Simon Wunderlich
Cc: linux-wireless, victorg, linville, kgiori, zefir.kurtisi, adrian,
j, coelho, assaf, igalc, nbd, mathias.kretschmer,
Simon Wunderlich
On Thu, 2012-12-13 at 14:58 +0100, Simon Wunderlich wrote:
> From: Victor Goldenshtein <victorg@ti.com>
>
> Add NL80211_CMD_AP_CH_SWITCH command which
> triggers an AP channel switch process.
>
> Usermode notified about channel switch complete
> event with NL80211_CMD_CH_SWITCH_NOTIFY.
>
> Usermode (hostapd) is responsible to update the
> channel switch announcement IE in the beacon
> prior and after the channel switch operation.
So ... hostapd is also responsible for counting down the "count"? This
didn't seem to be the case last I asked?
Then why is it responsible for creating the CSA IE? Should that be in
the kernel maybe? Or the IE be given to this command?
And then maybe the post-switch beacon IEs should be given to the command
as well, to avoid races as well as making it easier to manage this with
smarter firmware (say full-MAC drivers)?
Also, we already have an event to notify of an AP channel change, maybe
that should be used? If not, why not?
johannes
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCHv5 7/8] mac80211: add ap channel switch command/event
2012-12-13 13:58 ` [PATCHv5 7/8] mac80211: add ap channel switch command/event Simon Wunderlich
@ 2013-01-02 13:46 ` Johannes Berg
2013-01-03 7:41 ` Simon Wunderlich
2013-01-02 13:47 ` Johannes Berg
1 sibling, 1 reply; 27+ messages in thread
From: Johannes Berg @ 2013-01-02 13:46 UTC (permalink / raw)
To: Simon Wunderlich
Cc: linux-wireless, victorg, linville, kgiori, zefir.kurtisi, adrian,
j, coelho, assaf, igalc, nbd, mathias.kretschmer,
Simon Wunderlich
On Thu, 2012-12-13 at 14:58 +0100, Simon Wunderlich wrote:
> + drv_ap_channel_switch(local, ap_ch_switch);
> + return 0;
Why is that not allowed to fail in the driver?
johannes
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCHv5 7/8] mac80211: add ap channel switch command/event
2012-12-13 13:58 ` [PATCHv5 7/8] mac80211: add ap channel switch command/event Simon Wunderlich
2013-01-02 13:46 ` Johannes Berg
@ 2013-01-02 13:47 ` Johannes Berg
2013-01-03 7:47 ` Simon Wunderlich
1 sibling, 1 reply; 27+ messages in thread
From: Johannes Berg @ 2013-01-02 13:47 UTC (permalink / raw)
To: Simon Wunderlich
Cc: linux-wireless, victorg, linville, kgiori, zefir.kurtisi, adrian,
j, coelho, assaf, igalc, nbd, mathias.kretschmer,
Simon Wunderlich
On Thu, 2012-12-13 at 14:58 +0100, Simon Wunderlich wrote:
> + mutex_lock(&local->mtx);
> + if (local->ap_cs_chandef.chan->flags & IEEE80211_CHAN_RADAR) {
> + sdata_info(sdata, "changing to DFS channel\n");
> + /* when changing to a DFS channel, stop AP. Userspace must
> + * restart AP or do start radar detection first.
> + */
> + stop_ap = true;
I don't see any value in this. You might just as well simply forbid
requesting a channel change to a DFS channel, hostapd could then stop
instead of doing the switch.
> + } else {
> + /* update the device channel directly */
> + sdata_info(sdata, "changing to non-DFS channel\n");
> +
> + /* TODO: _oper_channel is deprecated ... use
> + * vif_release/use_channel instead? In this case, we must make
> + * sure that interface is down first ...
> + */
Well, most likely need to modify the existing channel context instead.
However, that's tricky, and what if there are other interfaces, what
happens to those?
johannes
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCHv5 0/8] Add DFS master ability
2012-12-13 13:58 [PATCHv5 0/8] Add DFS master ability Simon Wunderlich
` (7 preceding siblings ...)
2012-12-13 13:58 ` [PATCHv5 8/8] nl80211: allow DFS in start_ap Simon Wunderlich
@ 2013-01-02 13:53 ` Johannes Berg
2013-01-02 14:44 ` Simon Wunderlich
8 siblings, 1 reply; 27+ messages in thread
From: Johannes Berg @ 2013-01-02 13:53 UTC (permalink / raw)
To: Simon Wunderlich
Cc: linux-wireless, victorg, linville, kgiori, zefir.kurtisi, adrian,
j, coelho, assaf, igalc, nbd, mathias.kretschmer,
Simon Wunderlich
> I'm sending this as patch to keep the versioning, although it can be
> considered as RFC, I would be suprised if all single channel/single
> interface aspects were considered correctly. :)
:)
I think we need a bit more "design review" first.
To me, the open questions are:
* Should switching to a DFS channel be allowed at all? How so, if radar
can't be tested before? You just stop the AP instead but userspace
can do that just as well.
* What happens with multiple virtual interfaces? You allow a single
channel context only which makes sense, but that doesn't disallow
things like having a client + AP, and then the client switching away
because the P2P GO it was connected to randomly decided to switch.
This would break radar detection. (1) What should happen in this
case?
* To avoid that problem, could restrict to a single virtual interface.
However, that's unlikely to be sufficient -- you'd want to still be
able to implement multi-BSSID APs which then switch together etc.
* That raises another interesting question -- should multiple BSSIDs on
the same channel really *all* call the driver's ap_channel_switch()
callback? That seems ... strange!
* Do we need any software channel switch handling?
Generally the biggest issue is around multi-channel channel switch
behaviour I think. Any good ideas?
johannes
(1) Actually today it would either break the AP (channel contexts NOT
supported by the driver) or disconnect the client (otherwise)
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCHv5 0/8] Add DFS master ability
2013-01-02 13:53 ` [PATCHv5 0/8] Add DFS master ability Johannes Berg
@ 2013-01-02 14:44 ` Simon Wunderlich
2013-01-04 13:21 ` Johannes Berg
0 siblings, 1 reply; 27+ messages in thread
From: Simon Wunderlich @ 2013-01-02 14:44 UTC (permalink / raw)
To: Johannes Berg
Cc: Simon Wunderlich, linux-wireless, victorg, linville, kgiori,
zefir.kurtisi, adrian, j, coelho, assaf, igalc, nbd,
mathias.kretschmer, Simon Wunderlich
[-- Attachment #1: Type: text/plain, Size: 3426 bytes --]
Hello Johannes,
thank you very much for the review!
On Wed, Jan 02, 2013 at 02:53:43PM +0100, Johannes Berg wrote:
>
> > I'm sending this as patch to keep the versioning, although it can be
> > considered as RFC, I would be suprised if all single channel/single
> > interface aspects were considered correctly. :)
>
> :)
>
> I think we need a bit more "design review" first.
Good idea. :D
>
> To me, the open questions are:
> * Should switching to a DFS channel be allowed at all? How so, if radar
> can't be tested before? You just stop the AP instead but userspace
> can do that just as well.
The idea was to allow counting down the TBTT/count field of the CSA IE within
the driver - this can't be done properly by userspace.
Also, the transmission must be stopped on the new channel, so the idea was
to do this in kernel space right after the counting is finished. The idea
was to skip the additional enable_tx call which was originally proposed,
but it seems to create more troubles than it saves.
So maybe we should go back to enable_tx to re-enable the AP after a
switch into a DFS channel (with block-tx on).
Unlike Victors proposal, I'd suggest to skip enable_tx when starting the
AP the first time - just doing cac/radar_detect and start_ap should be enough.
> * What happens with multiple virtual interfaces? You allow a single
> channel context only which makes sense, but that doesn't disallow
> things like having a client + AP, and then the client switching away
> because the P2P GO it was connected to randomly decided to switch.
> This would break radar detection. (1) What should happen in this
> case?
Actually I thought I had succesfully disabled multiple interfaces in general
when DFS channels are used. Maybe I missed something?
For now, I'd prefer having only a single interface when doing DFS.
> * To avoid that problem, could restrict to a single virtual interface.
> However, that's unlikely to be sufficient -- you'd want to still be
> able to implement multi-BSSID APs which then switch together etc.
Agreed. In the first step, we could allow multi-BSSID APs. When one hostapd
instance controls these APs, it should have enough information to coordinate
the CSAs on all APs.
> * That raises another interesting question -- should multiple BSSIDs on
> the same channel really *all* call the driver's ap_channel_switch()
> callback? That seems ... strange!
Hmm, the channel should only be switched once, that's right.
What about:
* set CSA IEs in the beacons of all APs
* call ap_channel_switch once for all APs on the phy
* report switched channel back for all APs
* remove CSA IEs
> * Do we need any software channel switch handling?
Don't know what you specifically mean.
A more interesting case will be CSAs for IBSS (later), as the beacons are
handled by the drivers/mac80211 only.
>
> Generally the biggest issue is around multi-channel channel switch
> behaviour I think. Any good ideas?
For the MultiSSID-APs I think it's possible as roughly described above.
However mixed cases like AP+Client or AP+IBSS will be more interesting,
and I don't have any good idea for this yet...
>
> johannes
>
> (1) Actually today it would either break the AP (channel contexts NOT
> supported by the driver) or disconnect the client (otherwise)
>
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 198 bytes --]
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCHv5 2/8] cfg/mac80211: add dfs capability to cfg80211_reg_can_beacon()
2013-01-02 13:36 ` Johannes Berg
@ 2013-01-02 14:45 ` Simon Wunderlich
0 siblings, 0 replies; 27+ messages in thread
From: Simon Wunderlich @ 2013-01-02 14:45 UTC (permalink / raw)
To: Johannes Berg
Cc: Simon Wunderlich, linux-wireless, victorg, linville, kgiori,
zefir.kurtisi, adrian, j, coelho, assaf, igalc, nbd,
mathias.kretschmer, Simon Wunderlich
[-- Attachment #1: Type: text/plain, Size: 1003 bytes --]
On Wed, Jan 02, 2013 at 02:36:58PM +0100, Johannes Berg wrote:
> On Thu, 2012-12-13 at 14:58 +0100, Simon Wunderlich wrote:
>
> > * @chandef: the channel definition
> > + * @dfs_capab: supported DFS bandwidth
> > *
> > * This function returns true if there is no secondary channel or the secondary
> > * channel(s) can be used for beaconing (i.e. is not a radar channel etc.)
> > */
> > bool cfg80211_reg_can_beacon(struct wiphy *wiphy,
> > - struct cfg80211_chan_def *chandef);
> > + struct cfg80211_chan_def *chandef,
> > + enum nl80211_chan_width dfs_capab);
>
> Hm how does that make sense? The chandef contains a width? It seems like
> the check whether or not DFS is supported (should be a bitfield btw)
> should be outside of this function?
I'll change the DFS support capabilities to a bitfield and drop this patch. The
bitfield can be part of wiphy, and thus doesn't need to be passed down,
making this patch obsolete.
Cheers,
Simon
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 198 bytes --]
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCHv5 6/8] nl80211/cfg80211: add ap channel switch command
2013-01-02 13:45 ` Johannes Berg
@ 2013-01-02 15:05 ` Simon Wunderlich
2013-01-04 13:08 ` Johannes Berg
0 siblings, 1 reply; 27+ messages in thread
From: Simon Wunderlich @ 2013-01-02 15:05 UTC (permalink / raw)
To: Johannes Berg
Cc: Simon Wunderlich, linux-wireless, victorg, linville, kgiori,
zefir.kurtisi, adrian, j, coelho, assaf, igalc, nbd,
mathias.kretschmer, Simon Wunderlich
[-- Attachment #1: Type: text/plain, Size: 1940 bytes --]
On Wed, Jan 02, 2013 at 02:45:19PM +0100, Johannes Berg wrote:
> On Thu, 2012-12-13 at 14:58 +0100, Simon Wunderlich wrote:
> > From: Victor Goldenshtein <victorg@ti.com>
> >
> > Add NL80211_CMD_AP_CH_SWITCH command which
> > triggers an AP channel switch process.
> >
> > Usermode notified about channel switch complete
> > event with NL80211_CMD_CH_SWITCH_NOTIFY.
> >
> > Usermode (hostapd) is responsible to update the
> > channel switch announcement IE in the beacon
> > prior and after the channel switch operation.
>
> So ... hostapd is also responsible for counting down the "count"? This
> didn't seem to be the case last I asked?
No, the idea is that hostapd just provides the CSA IE. Decrementing
the TBTT before each beacon should be performed by the low level driver,
as it's the only one which can do that (IMHO). Userspace can't do that.
There is no difference here to Victors proposal.
>
> Then why is it responsible for creating the CSA IE? Should that be in
> the kernel maybe? Or the IE be given to this command?
Right now, hostapd creates the whole beacon, so we consider it responsible
for doing changes. Or is there any common implemented infrastructure in the
kernel right now to modify the beacon? As far as I know, Mesh and IBSS create
new beacons on their own (but do not modify them), and APs beacon is supplied by
userspace.
>
> And then maybe the post-switch beacon IEs should be given to the command
> as well, to avoid races as well as making it easier to manage this with
> smarter firmware (say full-MAC drivers)?
That's not a bad idea actually ...
>
> Also, we already have an event to notify of an AP channel change, maybe
> that should be used? If not, why not?
The NL80211_CMD_CH_SWITCH_NOTIFY event is already present and not introduced
with this patch, but reused for AP. Which other event do you mean for this
purpose?
Thanks,
Simon
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 198 bytes --]
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCHv5 3/8] nl80211/cfg80211: add radar detection command/event
2013-01-02 13:39 ` Johannes Berg
@ 2013-01-03 7:35 ` Simon Wunderlich
0 siblings, 0 replies; 27+ messages in thread
From: Simon Wunderlich @ 2013-01-03 7:35 UTC (permalink / raw)
To: Johannes Berg
Cc: Simon Wunderlich, linux-wireless, victorg, linville, kgiori,
zefir.kurtisi, adrian, j, coelho, assaf, igalc, nbd,
mathias.kretschmer, Simon Wunderlich
[-- Attachment #1: Type: text/plain, Size: 2136 bytes --]
On Wed, Jan 02, 2013 at 02:39:00PM +0100, Johannes Berg wrote:
> On Thu, 2012-12-13 at 14:58 +0100, Simon Wunderlich wrote:
>
> > +++ b/include/net/cfg80211.h
> > @@ -133,6 +133,11 @@ enum ieee80211_channel_flags {
> > * to enable this, this is useful only on 5 GHz band.
> > * @orig_mag: internal use
> > * @orig_mpwr: internal use
> > + * @radar_detect_timeout: this timeout indicates the end of the channel
> > + * availability check for radar channels (in jiffies), only after this
> > + * period the user may initiate the tx on the channel.
> > + * @cac_type: indicates that channel availability check is started for this
> > + * channel type.
> > */
> > struct ieee80211_channel {
> > enum ieee80211_band band;
> > @@ -145,6 +150,9 @@ struct ieee80211_channel {
> > bool beacon_found;
> > u32 orig_flags;
> > int orig_mag, orig_mpwr;
> > + unsigned long radar_detect_timeout;
> > + enum nl80211_channel_type cac_type;
> > + bool cac_started;
>
> Since we lock a channel, all of these should probably move to the
> rdev/wiphy struct, I think.
Hm, but when we have completed CAC on phy A, we could use the same
channel on phy B too, right?
That would be handy if one has two WiFi module and uses one only for
CAC/radar detection (e.g. checking other channels), and another one
doing the real AP service.
>
> And then the code checking channel contexts needs to be extended to not
> allow another while a channel context is in use:
>
> > + mutex_lock(&rdev->devlist_mtx);
> > + err = cfg80211_can_use_chan(rdev, wdev, chandef.chan,
> > + CHAN_MODE_SINGLE_ONLY);
> > + mutex_unlock(&rdev->devlist_mtx);
>
> This only does a spot check, keeping state needs to be handled
> separately.
I've extended cfg80211_can_use_iftype_chan() to check for other contexts
in the patch 1 of this series. This should make sure that only one single
mode context can be added, and it can't be added if other contexts are already
present. So you say that is not sufficient?
I guess I'm still not fully understanding the channel context concept ...
Cheers,
Simon
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 198 bytes --]
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCHv5 4/8] mac80211: add radar detection command/event
2013-01-02 13:40 ` Johannes Berg
@ 2013-01-03 7:36 ` Simon Wunderlich
0 siblings, 0 replies; 27+ messages in thread
From: Simon Wunderlich @ 2013-01-03 7:36 UTC (permalink / raw)
To: Johannes Berg
Cc: Simon Wunderlich, linux-wireless, victorg, linville, kgiori,
zefir.kurtisi, adrian, j, coelho, assaf, igalc, nbd,
mathias.kretschmer, Simon Wunderlich
[-- Attachment #1: Type: text/plain, Size: 762 bytes --]
On Wed, Jan 02, 2013 at 02:40:29PM +0100, Johannes Berg wrote:
> On Thu, 2012-12-13 at 14:58 +0100, Simon Wunderlich wrote:
>
> > + int (*start_radar_detection)(struct ieee80211_hw *hw,
> > + struct ieee80211_vif *vif,
> > + struct ieee80211_channel *chan);
>
> pass a chandef?
Good idea, will change that.
> > +void ieee80211_radar_detected(struct ieee80211_vif *vif,
> > + struct ieee80211_channel *chan, gfp_t gfp);
>
> Here you probably don't need to pass the channel, once the tracking in
> cfg80211 moves into the sdata (or even local) struct the same can happen
> in mac80211.
Yep, we should change this depending on the result of the discussion whether
we want to change the tracking.
Cheers,
Simon
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 198 bytes --]
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCHv5 7/8] mac80211: add ap channel switch command/event
2013-01-02 13:46 ` Johannes Berg
@ 2013-01-03 7:41 ` Simon Wunderlich
0 siblings, 0 replies; 27+ messages in thread
From: Simon Wunderlich @ 2013-01-03 7:41 UTC (permalink / raw)
To: Johannes Berg
Cc: Simon Wunderlich, linux-wireless, victorg, linville, kgiori,
zefir.kurtisi, adrian, j, coelho, assaf, igalc, nbd,
mathias.kretschmer, Simon Wunderlich
[-- Attachment #1: Type: text/plain, Size: 372 bytes --]
On Wed, Jan 02, 2013 at 02:46:02PM +0100, Johannes Berg wrote:
> On Thu, 2012-12-13 at 14:58 +0100, Simon Wunderlich wrote:
>
> > + drv_ap_channel_switch(local, ap_ch_switch);
> > + return 0;
>
> Why is that not allowed to fail in the driver?
Fair question. Userspace should handle this if it fails (for whatever
reason). Will change that.
Cheers,
Simon
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 198 bytes --]
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCHv5 7/8] mac80211: add ap channel switch command/event
2013-01-02 13:47 ` Johannes Berg
@ 2013-01-03 7:47 ` Simon Wunderlich
2013-01-04 13:10 ` Johannes Berg
0 siblings, 1 reply; 27+ messages in thread
From: Simon Wunderlich @ 2013-01-03 7:47 UTC (permalink / raw)
To: Johannes Berg
Cc: Simon Wunderlich, linux-wireless, victorg, linville, kgiori,
zefir.kurtisi, adrian, j, coelho, assaf, igalc, nbd,
mathias.kretschmer, Simon Wunderlich
[-- Attachment #1: Type: text/plain, Size: 1780 bytes --]
On Wed, Jan 02, 2013 at 02:47:49PM +0100, Johannes Berg wrote:
> On Thu, 2012-12-13 at 14:58 +0100, Simon Wunderlich wrote:
>
> > + mutex_lock(&local->mtx);
> > + if (local->ap_cs_chandef.chan->flags & IEEE80211_CHAN_RADAR) {
> > + sdata_info(sdata, "changing to DFS channel\n");
> > + /* when changing to a DFS channel, stop AP. Userspace must
> > + * restart AP or do start radar detection first.
> > + */
> > + stop_ap = true;
>
> I don't see any value in this. You might just as well simply forbid
> requesting a channel change to a DFS channel, hostapd could then stop
> instead of doing the switch.
>
We explicitly want the channel switch, this was the original idea in 802.11h
- announce the next channel, then switch. To announce the next channel, we
need to allow this.
As discussed before, doing stop_ap here is probably not a good idea. We
can change that back to let the driver disable transmissions and expect
an explicit enable_tx call from userspace after CAC on the new channel.
> > + } else {
> > + /* update the device channel directly */
> > + sdata_info(sdata, "changing to non-DFS channel\n");
> > +
> > + /* TODO: _oper_channel is deprecated ... use
> > + * vif_release/use_channel instead? In this case, we must make
> > + * sure that interface is down first ...
> > + */
>
> Well, most likely need to modify the existing channel context instead.
> However, that's tricky, and what if there are other interfaces, what
> happens to those?
That's a fair question ... for the current DFS implementation, I except to
only have one interface (single only context) - for now. We have the same
discussion in the other thread (general design questions), so let's discuss
it there.
Cheers,
Simon
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 198 bytes --]
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCHv5 6/8] nl80211/cfg80211: add ap channel switch command
2013-01-02 15:05 ` Simon Wunderlich
@ 2013-01-04 13:08 ` Johannes Berg
0 siblings, 0 replies; 27+ messages in thread
From: Johannes Berg @ 2013-01-04 13:08 UTC (permalink / raw)
To: Simon Wunderlich
Cc: linux-wireless, victorg, linville, kgiori, zefir.kurtisi, adrian,
j, coelho, igalc, nbd, mathias.kretschmer, Simon Wunderlich
On Wed, 2013-01-02 at 16:05 +0100, Simon Wunderlich wrote:
> > Also, we already have an event to notify of an AP channel change, maybe
> > that should be used? If not, why not?
>
> The NL80211_CMD_CH_SWITCH_NOTIFY event is already present and not introduced
> with this patch, but reused for AP. Which other event do you mean for this
> purpose?
Ah ok, never mind then.
johannes
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCHv5 7/8] mac80211: add ap channel switch command/event
2013-01-03 7:47 ` Simon Wunderlich
@ 2013-01-04 13:10 ` Johannes Berg
0 siblings, 0 replies; 27+ messages in thread
From: Johannes Berg @ 2013-01-04 13:10 UTC (permalink / raw)
To: Simon Wunderlich
Cc: linux-wireless, victorg, linville, kgiori, zefir.kurtisi, adrian,
j, coelho, igalc, nbd, mathias.kretschmer, Simon Wunderlich
On Thu, 2013-01-03 at 08:47 +0100, Simon Wunderlich wrote:
> On Wed, Jan 02, 2013 at 02:47:49PM +0100, Johannes Berg wrote:
> > On Thu, 2012-12-13 at 14:58 +0100, Simon Wunderlich wrote:
> >
> > > + mutex_lock(&local->mtx);
> > > + if (local->ap_cs_chandef.chan->flags & IEEE80211_CHAN_RADAR) {
> > > + sdata_info(sdata, "changing to DFS channel\n");
> > > + /* when changing to a DFS channel, stop AP. Userspace must
> > > + * restart AP or do start radar detection first.
> > > + */
> > > + stop_ap = true;
> >
> > I don't see any value in this. You might just as well simply forbid
> > requesting a channel change to a DFS channel, hostapd could then stop
> > instead of doing the switch.
> >
>
> We explicitly want the channel switch, this was the original idea in 802.11h
> - announce the next channel, then switch. To announce the next channel, we
> need to allow this.
>
> As discussed before, doing stop_ap here is probably not a good idea. We
> can change that back to let the driver disable transmissions and expect
> an explicit enable_tx call from userspace after CAC on the new channel.
I just don't see that the clients will wait a minute (?) for the CAC on
the new channel, they'll probably just disconnect and look for another
AP. So I guess the question is whether we should ever switch to a radar
channel ...
johannes
^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCHv5 0/8] Add DFS master ability
2013-01-02 14:44 ` Simon Wunderlich
@ 2013-01-04 13:21 ` Johannes Berg
0 siblings, 0 replies; 27+ messages in thread
From: Johannes Berg @ 2013-01-04 13:21 UTC (permalink / raw)
To: Simon Wunderlich
Cc: linux-wireless, victorg, linville, kgiori, zefir.kurtisi, adrian,
j, coelho, igalc, nbd, mathias.kretschmer, Simon Wunderlich
On Wed, 2013-01-02 at 15:44 +0100, Simon Wunderlich wrote:
> > To me, the open questions are:
> > * Should switching to a DFS channel be allowed at all? How so, if radar
> > can't be tested before? You just stop the AP instead but userspace
> > can do that just as well.
>
> The idea was to allow counting down the TBTT/count field of the CSA IE within
> the driver - this can't be done properly by userspace.
What if the driver doesn't do it either, say with ath9k it seems
mac80211 would have to do it and also switch the channel later. (That's
essentially what I was referring to when I said we might need a
"software implementation" on patch 7)
> Also, the transmission must be stopped on the new channel, so the idea was
> to do this in kernel space right after the counting is finished. The idea
> was to skip the additional enable_tx call which was originally proposed,
> but it seems to create more troubles than it saves.
I guess it depends on whether we switch to a radar channel or not.
However I'm not convinced that switching to a radar channel makes sense
at all -- it basically means the AP is dead for the clients.
Disconnecting all the clients instead would make more sense, it seems?
And in order to do that, we either just send each one a unicast deauth,
but if that keeps too much traffic active we might have to announce a
switch and then send deauth to everyone I guess anyway. But such a
switch could go to a non-radar channel, or we could even switch to a
non-radar channel first and then deauth all stations afterwards ...
All of that can be implemented without the ability to directly switch to
a radar channel though.
> > * What happens with multiple virtual interfaces? You allow a single
> > channel context only which makes sense, but that doesn't disallow
> > things like having a client + AP, and then the client switching away
> > because the P2P GO it was connected to randomly decided to switch.
> > This would break radar detection. (1) What should happen in this
> > case?
>
> Actually I thought I had succesfully disabled multiple interfaces in general
> when DFS channels are used. Maybe I missed something?
As we discussed, you missed actually locking the interface into CAC mode
so none of this ever happened -- see cfg80211_get_chan_state().
> For now, I'd prefer having only a single interface when doing DFS.
>
> > * To avoid that problem, could restrict to a single virtual interface.
> > However, that's unlikely to be sufficient -- you'd want to still be
> > able to implement multi-BSSID APs which then switch together etc.
>
> Agreed. In the first step, we could allow multi-BSSID APs. When one hostapd
> instance controls these APs, it should have enough information to coordinate
> the CSAs on all APs.
Yes. The question is what APIs it should use. Or maybe, with channel
contexts, the multiple BSSIDs could switch to different channels even?!
I don't think that makes sense, but hey...
> > * That raises another interesting question -- should multiple BSSIDs on
> > the same channel really *all* call the driver's ap_channel_switch()
> > callback? That seems ... strange!
>
> Hmm, the channel should only be switched once, that's right.
>
> What about:
> * set CSA IEs in the beacons of all APs
> * call ap_channel_switch once for all APs on the phy
> * report switched channel back for all APs
> * remove CSA IEs
Hmm ok with this approach it'd be problematic to set the
pre-/post-chanswitch beacon IEs in the command. We may have to allow the
command to affect a list of interfaces with some nested netlink
attributes.
Then you'd basically have
AP_CHANSWITCH
- interfaces:
- wlan0:
- pre-switch beacon
- post-switch beacon
- new chandef (for width etc.)
- wlan1: ...
- ...
We'd have to make sure all those interfaces are on the same channel
context when this happens, but that seems doable. Oh and all interfaces
have to be on the same wiphy as well, of course.
That needs to be reflected in all the various APIs too.
> > * Do we need any software channel switch handling?
>
> Don't know what you specifically mean.
(see above)
johannes
^ permalink raw reply [flat|nested] 27+ messages in thread
end of thread, other threads:[~2013-01-04 13:21 UTC | newest]
Thread overview: 27+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-12-13 13:58 [PATCHv5 0/8] Add DFS master ability Simon Wunderlich
2012-12-13 13:58 ` [PATCHv5 1/8] cfg80211: add CHAN_MODE_SINGLE_ONLY for DFS use Simon Wunderlich
2013-01-02 13:34 ` Johannes Berg
2012-12-13 13:58 ` [PATCHv5 2/8] cfg/mac80211: add dfs capability to cfg80211_reg_can_beacon() Simon Wunderlich
2013-01-02 13:36 ` Johannes Berg
2013-01-02 14:45 ` Simon Wunderlich
2012-12-13 13:58 ` [PATCHv5 3/8] nl80211/cfg80211: add radar detection command/event Simon Wunderlich
2013-01-02 13:39 ` Johannes Berg
2013-01-03 7:35 ` Simon Wunderlich
2012-12-13 13:58 ` [PATCHv5 4/8] mac80211: " Simon Wunderlich
2013-01-02 13:40 ` Johannes Berg
2013-01-03 7:36 ` Simon Wunderlich
2012-12-13 13:58 ` [PATCHv5 5/8] mac80211: check radar interaction with scan and roc Simon Wunderlich
2012-12-13 13:58 ` [PATCHv5 6/8] nl80211/cfg80211: add ap channel switch command Simon Wunderlich
2013-01-02 13:45 ` Johannes Berg
2013-01-02 15:05 ` Simon Wunderlich
2013-01-04 13:08 ` Johannes Berg
2012-12-13 13:58 ` [PATCHv5 7/8] mac80211: add ap channel switch command/event Simon Wunderlich
2013-01-02 13:46 ` Johannes Berg
2013-01-03 7:41 ` Simon Wunderlich
2013-01-02 13:47 ` Johannes Berg
2013-01-03 7:47 ` Simon Wunderlich
2013-01-04 13:10 ` Johannes Berg
2012-12-13 13:58 ` [PATCHv5 8/8] nl80211: allow DFS in start_ap Simon Wunderlich
2013-01-02 13:53 ` [PATCHv5 0/8] Add DFS master ability Johannes Berg
2013-01-02 14:44 ` Simon Wunderlich
2013-01-04 13:21 ` Johannes Berg
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).