2012-06-18 14:49:44

by Victor Goldenshtein

[permalink] [raw]
Subject: [PATCH 0/7] nl/cfg/mac80211: add DFS master ability

In continuation to proposed RFC, this patch set (with hostap patch series) adds support for DFS (Dynamic Frequency Selection) according 802.11h.


Main idea
=========

DFS master algorithm is implemented in the hostapd, while nl/cfg/mac80211 will pipe relevant commands/events to the driver/hostapd.
Based on the assumption that the device/driver supports radar interference detection i.e., it is capable to generate radar_detected event by using different pattern detection techniques:

1. Pattern detection in the HW: the device generates 'radar_detected' event.
2. Pattern detection in the driver: the driver receives radar pulses from the device and generates 'radar detected' event.


Main DFS procedures
===================

1. Hostapd gets driver's dfs and channel switch capabilities.
2. If 80211h is enabled in the hostapd.conf, the driver supports one of the above radar detection techniques and supports an AP channel switch, hostapd may use DFS channels.
3. Hostapd selects an operational channel (default from hostapd.conf), if selected channel is a DFS channel, hostapd sends start_radar_detection command to the device/driver which starts monitoring for radar interference while hostapd sets a timer for a CAC (Channel Availability Check) time, which is 60 seconds.
4. As CAC timer expires and no radar has been detected, hostapd may continue with the init flow, otherwise if interference is detected hostapd selects another channel (random selection) and repeats the CAC on the new channel (in case the new channel is also a DFS channel), while the original channel is added to a "black list" for a period of ''No-Occupancy'' time (time that the channel can't be used/selected).
5. While using the channel the device/driver continuously monitors for potential radar interference. If interference is detected hostapd is notified with 'radar detected' event, which selects a new channel and triggers a channel switch procedure, if the new channel is also a DFS channel, hostapd performs the CAC test, once it's successfully passed hostapd instructs the driver to initiate the transmission on the channel.


Updates & changes from the proposed RFC
=======================================

1. Added safeguards to protect from userspace stupidities to enable TX on DFS channel prior performing a CAC.
2. Removed IEEE80211_HW_SUPPORTS_RADAR_DETECTION & WIPHY_FLAG_SUPPORTS_DFS flags.
3. Removed "hw_ prefix" & "_notify" suffix from function names.
4. Don't set default return value “ int ret = -ENOENT” In the ieee80211_dfs_start_radar_detection().
5. Removed mutex protection from drv_start_radar_detection() & drv_dfs_en_tx().
6. Change the tracer to trace_drv_return_int() in drv_start_radar_detection & drv_dfs_en_tx.
7. Added "dfs_supported" sanity checks in.
8. Updated commit log in - mac80211: add radar detection command/event.
9. Renamed NL80211_CMD_DFS_RADAR_DETECTION to CMD_RADAR_DETECT.
10. Renamed dfs_start_radar_detection() to start_radar_detection().
11. Added “unit” in  "@freq: radar detected" event documentation.
12. Removed ASSERT_RDEV_LOCK from nl80211_dfs_start_radar_detection, nl80211_dfs_en_tx and nl80211_ap_channel_switch.
13. Updated documentation for the CMD_RADAR_DETECT.
14. Updated commit log in - nl80211/cfg80211: add ap channel switch command/event.
15. New "NL80211_FEATURE_AP_CH_SWITCH" which is enabled if drv_ap_channel_switch() is set by the driver.
16. New "ieee80211_ap_channel_switch" struct & drv_ap_channel_switch() callback.
17. Moved the “if (!new_ch || new_ch->flags&  IEEE80211_CHAN_DISABLED)” from "mac80211: add ap channel switch command/event" to upper nl80211/cfg80211 layer.
18. Removed the “nl80211_put_feature_flags, driver will set DFS capabilities directly.


Victor Goldenshtein (7):
nl80211/cfg80211: add radar detection command/event
mac80211: add radar detection command/event
nl80211/cfg80211: add ability to enable TX on op-channel
mac80211: add ability to enable TX on op-channel
nl80211/cfg80211: add ap channel switch command/event
mac80211: add ap channel switch command/event
mac80211: add DFS support to monitor interface

include/linux/nl80211.h | 43 ++++++++++
include/net/cfg80211.h | 40 +++++++++
include/net/mac80211.h | 60 ++++++++++++++
net/mac80211/cfg.c | 57 +++++++++++++
net/mac80211/driver-ops.h | 37 +++++++++
net/mac80211/driver-trace.h | 43 ++++++++++
net/mac80211/main.c | 3 +
net/mac80211/mlme.c | 17 ++++
net/mac80211/tx.c | 14 ++--
net/wireless/core.h | 6 ++
net/wireless/mlme.c | 47 +++++++++++
net/wireless/nl80211.c | 189 +++++++++++++++++++++++++++++++++++++++++++
net/wireless/nl80211.h | 10 +++
13 files changed, 560 insertions(+), 6 deletions(-)

--
1.7.5.4



2012-06-20 12:04:03

by Luciano Coelho

[permalink] [raw]
Subject: Re: [PATCH 0/7] nl/cfg/mac80211: add DFS master ability

On Wed, 2012-06-20 at 14:02 +0300, Goldenshtein, Victor wrote:
> On Wed, Jun 20, 2012 at 1:49 PM, Johannes Berg
> <[email protected]> wrote:
> > On Wed, 2012-06-20 at 13:47 +0300, Goldenshtein, Victor wrote:
> >> On Wed, Jun 20, 2012 at 1:34 PM, Zefir Kurtisi
> >> <[email protected]> wrote:
> >> > On 06/18/2012 04:46 PM, Victor Goldenshtein wrote:
> >> >> In continuation to proposed RFC, this patch set (with hostap patch series) adds support for DFS (Dynamic Frequency Selection) according 802.11h.
> >> >>
> >> >> [...]
> >> >
> >> > Thanks for the updated patches, Victor.
> >> >
> >> > Going to test them by preparing the ath9k interface.
> >> >
> >> > Right now they do not apply on top of wireless-testing, could you please
> >> > rebase? Thanks.
> >>
> >> The patches are on top of the master branch from:
> >> git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211.git
> >
> > Why would you use that instead of mac80211-next?
> >
>
> Will rebase on top of the mac80211-next.

Sorry, I think this was my mistake, because I told Victor to use this
tree. I associated mac80211.git with wireless-testing.git. Now I
realize that mac80211.git is like wireless.git (ie. contains patches
that should go to the current kernel, at the moment, 3.5).

I guess the best thing to do is to keep basing mac80211 patches on top
of linux-wireless.

--
Luca.


2012-06-18 14:50:33

by Victor Goldenshtein

[permalink] [raw]
Subject: [PATCH 7/7] mac80211: add DFS support to monitor interface

Stop dropping packets if we are on 'radar channel'
and the DFS is enabled/supported.

Signed-off-by: Victor Goldenshtein <[email protected]>
---
net/mac80211/tx.c | 14 ++++++++------
1 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index e453212..b6a7cee 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -1595,6 +1595,8 @@ netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb,
struct ieee80211_sub_if_data *tmp_sdata, *sdata;
u16 len_rthdr;
int hdrlen;
+ bool dfs_supported = !!(local->hw.wiphy->features &
+ NL80211_FEATURE_DFS);

/*
* Frame injection is not allowed if beaconing is not allowed
@@ -1607,13 +1609,13 @@ netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb,
* flag.
*
* Since AP mode uses monitor interfaces to inject/TX management
- * frames we can make AP mode the exception to this rule once it
- * supports radar detection as its implementation can deal with
- * radar detection by itself. We can do that later by adding a
- * monitor flag interfaces used for AP support.
+ * frames we can make AP mode the exception to this rule, in the
+ * case the driver supports radar detection, allow usage of radar
+ * channels.
*/
- if ((chan->flags & (IEEE80211_CHAN_NO_IBSS | IEEE80211_CHAN_RADAR |
- IEEE80211_CHAN_PASSIVE_SCAN)))
+ if ((!(chan->flags & IEEE80211_CHAN_RADAR) || !dfs_supported) &&
+ ((chan->flags & (IEEE80211_CHAN_NO_IBSS | IEEE80211_CHAN_RADAR |
+ IEEE80211_CHAN_PASSIVE_SCAN))))
goto fail;

/* check for not even having the fixed radiotap header part */
--
1.7.5.4


2012-06-18 14:59:23

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH 0/7] nl/cfg/mac80211: add DFS master ability

On Mon, 2012-06-18 at 17:46 +0300, Victor Goldenshtein wrote:
> In continuation to proposed RFC, this patch set (with hostap patch
> series) adds support for DFS (Dynamic Frequency Selection) according
> 802.11h.

Please fix coding style in this patchset first. There are various places
with bad indentation etc.

johannes


2012-06-20 11:02:10

by Victor Goldenshtein

[permalink] [raw]
Subject: Re: [PATCH 0/7] nl/cfg/mac80211: add DFS master ability

On Wed, Jun 20, 2012 at 1:49 PM, Johannes Berg
<[email protected]> wrote:
> On Wed, 2012-06-20 at 13:47 +0300, Goldenshtein, Victor wrote:
>> On Wed, Jun 20, 2012 at 1:34 PM, Zefir Kurtisi
>> <[email protected]> wrote:
>> > On 06/18/2012 04:46 PM, Victor Goldenshtein wrote:
>> >> In continuation to proposed RFC, this patch set (with hostap patch series) adds support for DFS (Dynamic Frequency Selection) according 802.11h.
>> >>
>> >> [...]
>> >
>> > Thanks for the updated patches, Victor.
>> >
>> > Going to test them by preparing the ath9k interface.
>> >
>> > Right now they do not apply on top of wireless-testing, could you please
>> > rebase? Thanks.
>>
>> The patches are on top of the master branch from:
>> git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211.git
>
> Why would you use that instead of mac80211-next?
>

Will rebase on top of the mac80211-next.


--
Thanks,
Victor.

2012-06-18 14:50:10

by Victor Goldenshtein

[permalink] [raw]
Subject: [PATCH 4/7] mac80211: add ability to enable TX on op-channel

Prior starting tx on DFS channels, the DFS master
device shall perform a Channel Availability Check
to ensure that there is no radar interference on
those channels. Once CAC done, the tx can be
enabled with ieee80211_dfs_en_tx().

Signed-off-by: Victor Goldenshtein <[email protected]>
---
include/net/mac80211.h | 4 ++++
net/mac80211/cfg.c | 15 +++++++++++++++
net/mac80211/driver-ops.h | 14 ++++++++++++++
net/mac80211/driver-trace.h | 6 ++++++
4 files changed, 39 insertions(+), 0 deletions(-)

diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index a2222cf..82e5ee7 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -2249,6 +2249,8 @@ enum ieee80211_rate_control_changed {
* @start_radar_detection: Start radar detection on current operational
* channel, once started it will continuously monitor for radars as long
* as the channel active.
+ * @dfs_en_tx: Once channel pass the DFS initial channel availability check,
+ * initiate the tx on the channel with this command.
*
*/
struct ieee80211_ops {
@@ -2392,6 +2394,8 @@ struct ieee80211_ops {
int (*start_radar_detection)(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_channel *chan);
+ int (*dfs_en_tx)(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ struct ieee80211_channel *chan);
};

/**
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 541b274..a48d055 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -2226,6 +2226,20 @@ static int ieee80211_start_radar_detection(struct wiphy *wiphy,
return ret;
}

+static int ieee80211_dfs_en_tx(struct wiphy *wiphy, struct net_device *dev,
+ struct ieee80211_channel *chan)
+{
+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+ struct ieee80211_local *local = sdata->local;
+ int ret = -ENOENT;
+
+ if (!local->ops->dfs_en_tx)
+ return -EOPNOTSUPP;
+
+ ret = drv_dfs_en_tx(local, sdata, chan);
+ return ret;
+}
+
static enum work_done_result
ieee80211_offchan_tx_done(struct ieee80211_work *wk, struct sk_buff *skb)
{
@@ -2995,4 +3009,5 @@ struct cfg80211_ops mac80211_config_ops = {
.get_et_stats = ieee80211_get_et_stats,
.get_et_strings = ieee80211_get_et_strings,
.start_radar_detection = ieee80211_start_radar_detection,
+ .dfs_en_tx = ieee80211_dfs_en_tx,
};
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index 57185df..f49b76b 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -343,6 +343,20 @@ static inline int drv_start_radar_detection(struct ieee80211_local *local,
return ret;
}

+static inline int drv_dfs_en_tx(struct ieee80211_local *local,
+ struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_channel *chan)
+{
+ int ret;
+
+ might_sleep();
+
+ trace_drv_dfs_en_tx(local, sdata);
+ ret = local->ops->dfs_en_tx(&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/driver-trace.h b/net/mac80211/driver-trace.h
index 4112aa3..6df02c4 100644
--- a/net/mac80211/driver-trace.h
+++ b/net/mac80211/driver-trace.h
@@ -490,6 +490,12 @@ DEFINE_EVENT(local_sdata_evt, drv_start_radar_detection,
TP_ARGS(local, sdata)
);

+DEFINE_EVENT(local_sdata_evt, drv_dfs_en_tx,
+ TP_PROTO(struct ieee80211_local *local,
+ struct ieee80211_sub_if_data *sdata),
+ TP_ARGS(local, sdata)
+);
+
DEFINE_EVENT(local_sdata_evt, drv_sched_scan_start,
TP_PROTO(struct ieee80211_local *local,
struct ieee80211_sub_if_data *sdata),
--
1.7.5.4


2012-06-20 10:47:30

by Victor Goldenshtein

[permalink] [raw]
Subject: Re: [PATCH 0/7] nl/cfg/mac80211: add DFS master ability

On Wed, Jun 20, 2012 at 1:34 PM, Zefir Kurtisi
<[email protected]> wrote:
> On 06/18/2012 04:46 PM, Victor Goldenshtein wrote:
>> In continuation to proposed RFC, this patch set (with hostap patch series) adds support for DFS (Dynamic Frequency Selection) according 802.11h.
>>
>> [...]
>
> Thanks for the updated patches, Victor.
>
> Going to test them by preparing the ath9k interface.
>
> Right now they do not apply on top of wireless-testing, could you please
> rebase? Thanks.

The patches are on top of the master branch from:
git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211.git

--
Thanks,
Victor.

2012-06-18 14:50:21

by Victor Goldenshtein

[permalink] [raw]
Subject: [PATCH 6/7] mac80211: add ap channel switch command/event

Add ieee80211_ap_process_chanswitch(), to handle a channel switch
request for AP/GO.

Add ieee80211_ap_ch_switch_complete_notify() which notifies upper
layers about channel switch complete event.

Signed-off-by: Victor Goldenshtein <[email protected]>
---
include/net/mac80211.h | 39 +++++++++++++++++++++++++++++++++++++++
net/mac80211/cfg.c | 26 ++++++++++++++++++++++++++
net/mac80211/driver-ops.h | 9 +++++++++
net/mac80211/driver-trace.h | 31 +++++++++++++++++++++++++++++++
net/mac80211/main.c | 3 +++
net/mac80211/mlme.c | 9 +++++++++
6 files changed, 117 insertions(+), 0 deletions(-)

diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 82e5ee7..79239a0 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -865,6 +865,32 @@ struct ieee80211_channel_switch {
};

/**
+ * struct ieee80211_ap_channel_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, as indicated by the AP.
+ * @post_switch_block_tx: Indicates whether transmission must be blocked after
+ * the scheduled channel switch, this should be set if the target channel
+ * is DFS channel.
+ * @channel: the new channel to switch to
+ * @count: the number of TBTT's until the channel switch event
+ */
+struct ieee80211_ap_channel_switch {
+ u64 timestamp;
+ bool block_tx;
+ bool post_switch_block_tx;
+ struct ieee80211_channel *channel;
+ u8 count;
+};
+
+/**
* enum ieee80211_vif_flags - virtual interface flags
*
* @IEEE80211_VIF_BEACON_FILTER: the device performs beacon filtering
@@ -2354,6 +2380,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);
+ void (*ap_channel_switch)(struct ieee80211_hw *hw,
+ struct ieee80211_ap_channel_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);
@@ -3578,6 +3606,17 @@ void ieee80211_cqm_rssi_notify(struct ieee80211_vif *vif,
void ieee80211_radar_detected(struct ieee80211_vif *vif, u16 freq, gfp_t gfp);

/**
+ * ieee80211_ap_ch_switch_complete_notify - inform a configured connection that
+ * channel switch is complete
+ *
+ * @vif: &struct ieee80211_vif pointer from the add_interface callback.
+ * @gfp: context flags
+ *
+ */
+void ieee80211_ap_ch_switch_complete_notify(struct ieee80211_vif *vif,
+ u16 freq, gfp_t gfp);
+
+/**
* ieee80211_get_operstate - get the operstate of the vif
*
* @vif: &struct ieee80211_vif pointer from the add_interface callback.
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index a48d055..d017972 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -2240,6 +2240,31 @@ static int ieee80211_dfs_en_tx(struct wiphy *wiphy, struct net_device *dev,
return ret;
}

+static int ieee80211_ap_process_chanswitch(struct wiphy *wiphy,
+ struct net_device *dev,
+ u32 count, bool block_tx,
+ bool post_switch_block_tx,
+ struct ieee80211_channel *new_ch)
+{
+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+ struct ieee80211_local *local = sdata->local;
+ struct ieee80211_ap_channel_switch ap_ch_switch;
+
+ if (!local->ops->channel_switch)
+ return -EOPNOTSUPP;
+
+ memset(&ap_ch_switch, 0, sizeof(ap_ch_switch));
+ ap_ch_switch.channel = new_ch;
+ ap_ch_switch.count = count;
+ ap_ch_switch.block_tx = block_tx;
+ ap_ch_switch.post_switch_block_tx = post_switch_block_tx;
+
+ mutex_lock(&local->mtx);
+ drv_ap_channel_switch(local, &ap_ch_switch);
+ mutex_unlock(&local->mtx);
+ return 0;
+}
+
static enum work_done_result
ieee80211_offchan_tx_done(struct ieee80211_work *wk, struct sk_buff *skb)
{
@@ -3010,4 +3035,5 @@ struct cfg80211_ops mac80211_config_ops = {
.get_et_strings = ieee80211_get_et_strings,
.start_radar_detection = ieee80211_start_radar_detection,
.dfs_en_tx = ieee80211_dfs_en_tx,
+ .ap_channel_switch = ieee80211_ap_process_chanswitch,
};
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index f49b76b..402f46e 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -711,6 +711,15 @@ static inline void drv_channel_switch(struct ieee80211_local *local,
trace_drv_return_void(local);
}

+static inline void drv_ap_channel_switch(struct ieee80211_local *local,
+ struct ieee80211_ap_channel_switch *ap_ch_switch)
+{
+ might_sleep();
+
+ trace_drv_ap_channel_switch(local, ap_ch_switch);
+ local->ops->ap_channel_switch(&local->hw, ap_ch_switch);
+ trace_drv_return_void(local);
+}

static inline int drv_set_antenna(struct ieee80211_local *local,
u32 tx_ant, u32 rx_ant)
diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h
index 6df02c4..972be66 100644
--- a/net/mac80211/driver-trace.h
+++ b/net/mac80211/driver-trace.h
@@ -927,6 +927,37 @@ TRACE_EVENT(drv_channel_switch,
)
);

+TRACE_EVENT(drv_ap_channel_switch,
+ TP_PROTO(struct ieee80211_local *local,
+ struct ieee80211_ap_channel_switch *ap_ch_switch),
+
+ TP_ARGS(local, ap_ch_switch),
+
+ TP_STRUCT__entry(
+ LOCAL_ENTRY
+ __field(u64, timestamp)
+ __field(bool, block_tx)
+ __field(bool, post_switch_block_tx)
+ __field(u16, freq)
+ __field(u8, count)
+ ),
+
+ TP_fast_assign(
+ LOCAL_ASSIGN;
+ __entry->timestamp = ap_ch_switch->timestamp;
+ __entry->block_tx = ap_ch_switch->block_tx;
+ __entry->post_switch_block_tx =
+ ap_ch_switch->post_switch_block_tx;
+ __entry->freq = ap_ch_switch->channel->center_freq;
+ __entry->count = ap_ch_switch->count;
+ ),
+
+ TP_printk(
+ LOCAL_PR_FMT " new freq:%u count:%d",
+ LOCAL_PR_ARG, __entry->freq, __entry->count
+ )
+);
+
TRACE_EVENT(drv_set_antenna,
TP_PROTO(struct ieee80211_local *local, u32 tx_ant, u32 rx_ant, int ret),

diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index f5548e9..18094cc 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -567,6 +567,9 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
wiphy->features = NL80211_FEATURE_SK_TX_STATUS |
NL80211_FEATURE_HT_IBSS;

+ 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 37ed827..ab7e430 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -3570,6 +3570,15 @@ void ieee80211_radar_detected(struct ieee80211_vif *vif, u16 freq, gfp_t gfp)
}
EXPORT_SYMBOL(ieee80211_radar_detected);

+void ieee80211_ap_ch_switch_complete_notify(struct ieee80211_vif *vif,
+ u16 freq, gfp_t gfp)
+{
+ struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
+
+ cfg80211_ap_ch_switch_complete_notify(sdata->dev, freq, gfp);
+}
+EXPORT_SYMBOL(ieee80211_ap_ch_switch_complete_notify);
+
unsigned char ieee80211_get_operstate(struct ieee80211_vif *vif)
{
struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
--
1.7.5.4


2012-06-20 06:09:36

by Kalle Valo

[permalink] [raw]
Subject: Re: [PATCH 7/7] mac80211: add DFS support to monitor interface

Luciano Coelho <[email protected]> writes:

> On Tue, 2012-06-19 at 09:44 +0300, Kalle Valo wrote:
>> On 06/18/2012 05:46 PM, Victor Goldenshtein wrote:
>> > Stop dropping packets if we are on 'radar channel'
>> > and the DFS is enabled/supported.
>> >
>> > Signed-off-by: Victor Goldenshtein <[email protected]>
>>
>> Why? I'm not very familiar with DFS so this change is not clear to me.
>
> That's not a good excuse. :P

Heh, I didn't first get your comment but when I reread the patch. I
thought this patch was about dropping _received_ frames in a monitor
interface but it was actually about dropping _injected_ frames. Makes
better sense now :)

--
Kalle Valo

2012-06-18 15:04:17

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH 0/7] nl/cfg/mac80211: add DFS master ability

On Mon, 2012-06-18 at 18:02 +0300, Goldenshtein, Victor wrote:
> On Mon, Jun 18, 2012 at 5:59 PM, Johannes Berg
> <[email protected]> wrote:
> > On Mon, 2012-06-18 at 17:46 +0300, Victor Goldenshtein wrote:
> >> In continuation to proposed RFC, this patch set (with hostap patch
> >> series) adds support for DFS (Dynamic Frequency Selection) according
> >> 802.11h.
> >
> > Please fix coding style in this patchset first. There are various places
> > with bad indentation etc.
> >
> > johannes
> >
>
> I have checked all patches with checkpatch, zero warnings.
> Maybe only the cover letter has some style problems?

checkpatch isn't a replacement for reviewing code :-)

try --strict anyway

e.g.

+ if ((!(chan->flags & IEEE80211_CHAN_RADAR) || !dfs_supported) &&
+ ((chan->flags & (IEEE80211_CHAN_NO_IBSS | IEEE80211_CHAN_RADAR |
+ IEEE80211_CHAN_PASSIVE_SCAN))))
goto fail;

johannes


2012-06-20 10:49:11

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH 0/7] nl/cfg/mac80211: add DFS master ability

On Wed, 2012-06-20 at 13:47 +0300, Goldenshtein, Victor wrote:
> On Wed, Jun 20, 2012 at 1:34 PM, Zefir Kurtisi
> <[email protected]> wrote:
> > On 06/18/2012 04:46 PM, Victor Goldenshtein wrote:
> >> In continuation to proposed RFC, this patch set (with hostap patch series) adds support for DFS (Dynamic Frequency Selection) according 802.11h.
> >>
> >> [...]
> >
> > Thanks for the updated patches, Victor.
> >
> > Going to test them by preparing the ath9k interface.
> >
> > Right now they do not apply on top of wireless-testing, could you please
> > rebase? Thanks.
>
> The patches are on top of the master branch from:
> git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211.git

Why would you use that instead of mac80211-next?

johannes



2012-06-18 14:49:50

by Victor Goldenshtein

[permalink] [raw]
Subject: [PATCH 1/7] nl80211/cfg80211: add radar detection command/event

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_DFS attribute which indicates
that driver/HW supports radar detection.

Signed-off-by: Victor Goldenshtein <[email protected]>
---
include/linux/nl80211.h | 7 +++++
include/net/cfg80211.h | 20 +++++++++++++
net/wireless/core.h | 6 ++++
net/wireless/mlme.c | 36 ++++++++++++++++++++++++
net/wireless/nl80211.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++
net/wireless/nl80211.h | 5 +++
6 files changed, 143 insertions(+), 0 deletions(-)

diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index a6959f7..ea6ce93 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -553,6 +553,9 @@
* %NL80211_ATTR_IFINDEX is now on %NL80211_ATTR_WIPHY_FREQ with
* %NL80211_ATTR_WIPHY_CHANNEL_TYPE.
*
+ * @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
*/
@@ -696,6 +699,8 @@ enum nl80211_commands {

NL80211_CMD_CH_SWITCH_NOTIFY,

+ NL80211_CMD_RADAR_DETECT,
+
/* add new commands above here */

/* used to define NL80211_CMD_MAX below */
@@ -2867,11 +2872,13 @@ enum nl80211_ap_sme_features {
* @NL80211_FEATURE_HT_IBSS: This driver supports IBSS with HT datarates.
* @NL80211_FEATURE_INACTIVITY_TIMER: This driver takes care of freeing up
* the connected inactive stations in AP mode.
+ * @NL80211_FEATURE_DFS: Radar detection is supported in the HW/driver.
*/
enum nl80211_feature_flags {
NL80211_FEATURE_SK_TX_STATUS = 1 << 0,
NL80211_FEATURE_HT_IBSS = 1 << 1,
NL80211_FEATURE_INACTIVITY_TIMER = 1 << 2,
+ NL80211_FEATURE_DFS = 1 << 3,
};

/**
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 0289d4c..32dfc1f 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -127,6 +127,9 @@ 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, only after this period the
+ * user may initiate the tx on the channel.
*/
struct ieee80211_channel {
enum ieee80211_band band;
@@ -139,6 +142,7 @@ struct ieee80211_channel {
bool beacon_found;
u32 orig_flags;
int orig_mag, orig_mpwr;
+ unsigned long radar_detect_timeout;
};

/**
@@ -1525,6 +1529,8 @@ struct cfg80211_gtk_rekey_data {
* @get_et_strings: Ethtool API to get a set of strings to describe stats
* and perhaps other supported types of ethtool data-sets.
* See @ethtool_ops.get_strings
+ *
+ * @start_radar_detection: Start radar detection in the driver.
*/
struct cfg80211_ops {
int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
@@ -1730,6 +1736,10 @@ struct cfg80211_ops {
struct ethtool_stats *stats, u64 *data);
void (*get_et_strings)(struct wiphy *wiphy, struct net_device *dev,
u32 sset, u8 *data);
+
+ int (*start_radar_detection)(struct wiphy *wiphy,
+ struct net_device *dev,
+ struct ieee80211_channel *chan);
};

/*
@@ -3268,6 +3278,16 @@ void cfg80211_cqm_rssi_notify(struct net_device *dev,
gfp_t gfp);

/**
+ * cfg80211_radar_detected - radar detection event
+ * @dev: network device
+ * @freq: radar detected on this channel frequency (in MHz)
+ * @gfp: context flags
+ *
+ * This function is called when a radar is detected on the current channel.
+ */
+void cfg80211_radar_detected(struct net_device *dev, u16 freq, gfp_t gfp);
+
+/**
* cfg80211_cqm_pktloss_notify - notify userspace about packetloss to peer
* @dev: network device
* @peer: peer's MAC address
diff --git a/net/wireless/core.h b/net/wireless/core.h
index 8523f38..03e9744 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -445,6 +445,12 @@ int cfg80211_set_freq(struct cfg80211_registered_device *rdev,
struct wireless_dev *wdev, int freq,
enum nl80211_channel_type channel_type);

+int cfg80211_start_radar_detection(struct cfg80211_registered_device *rdev,
+ struct net_device *dev,
+ struct ieee80211_channel *chan);
+
+u16 cfg80211_calculate_bitrate(struct rate_info *rate);
+
int ieee80211_get_ratemask(struct ieee80211_supported_band *sband,
const u8 *rates, unsigned int n_rates,
u32 *mask);
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
index eb90988..a641db6 100644
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
@@ -16,6 +16,8 @@
#include "core.h"
#include "nl80211.h"

+#define IEEE80211_DFS_MIN_CAC_TIME_MS 60000
+
void cfg80211_send_rx_auth(struct net_device *dev, const u8 *buf, size_t len)
{
struct wireless_dev *wdev = dev->ieee80211_ptr;
@@ -982,3 +984,37 @@ bool cfg80211_rx_unexpected_4addr_frame(struct net_device *dev,
return nl80211_unexpected_4addr_frame(dev, addr, gfp);
}
EXPORT_SYMBOL(cfg80211_rx_unexpected_4addr_frame);
+
+int cfg80211_start_radar_detection(struct cfg80211_registered_device *rdev,
+ struct net_device *dev,
+ struct ieee80211_channel *chan)
+{
+ int err;
+
+ if (!rdev->ops->start_radar_detection)
+ return -EOPNOTSUPP;
+
+ err = rdev->ops->start_radar_detection(&rdev->wiphy, dev, chan);
+ if (!err)
+ chan->radar_detect_timeout = jiffies +
+ msecs_to_jiffies(IEEE80211_DFS_MIN_CAC_TIME_MS);
+ else
+ chan->radar_detect_timeout = 0;
+
+ return err;
+}
+
+void cfg80211_radar_detected(struct net_device *dev, u16 freq, gfp_t gfp)
+{
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+ struct wiphy *wiphy = wdev->wiphy;
+ struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
+ struct ieee80211_channel *chan;
+
+ chan = ieee80211_get_channel(&rdev->wiphy, freq);
+ if (chan)
+ chan->radar_detect_timeout = 0;
+
+ nl80211_radar_detected_notify(rdev, freq, dev, gfp);
+}
+EXPORT_SYMBOL(cfg80211_radar_detected);
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 206465d..573c966 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -4248,6 +4248,31 @@ 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];
+ bool dfs_supported = !!(rdev->wiphy.features & NL80211_FEATURE_DFS);
+ int freq;
+ struct ieee80211_channel *chan;
+
+ if (!dfs_supported)
+ return -EOPNOTSUPP;
+
+ if (!info->attrs[NL80211_ATTR_WIPHY_FREQ])
+ return -EINVAL;
+
+ freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]);
+
+ chan = ieee80211_get_channel(&rdev->wiphy, freq);
+
+ if (!chan || !(chan->flags & IEEE80211_CHAN_RADAR))
+ return -EINVAL;
+
+ return cfg80211_start_radar_detection(rdev, dev, chan);
+}
+
static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb,
u32 seq, int flags,
struct cfg80211_registered_device *rdev,
@@ -6997,6 +7022,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,
+ },

};

@@ -8101,6 +8134,42 @@ void nl80211_ch_switch_notify(struct cfg80211_registered_device *rdev,
}

void
+nl80211_radar_detected_notify(struct cfg80211_registered_device *rdev,
+ u16 freq, 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, 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 01a1122..a333261 100644
--- a/net/wireless/nl80211.h
+++ b/net/wireless/nl80211.h
@@ -105,6 +105,11 @@ 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,
+ u16 freq, 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.5.4


2012-06-18 15:02:45

by Victor Goldenshtein

[permalink] [raw]
Subject: Re: [PATCH 0/7] nl/cfg/mac80211: add DFS master ability

On Mon, Jun 18, 2012 at 5:59 PM, Johannes Berg
<[email protected]> wrote:
> On Mon, 2012-06-18 at 17:46 +0300, Victor Goldenshtein wrote:
>> In continuation to proposed RFC, this patch set (with hostap patch
>> series) adds support for DFS (Dynamic Frequency Selection) according
>> 802.11h.
>
> Please fix coding style in this patchset first. There are various places
> with bad indentation etc.
>
> johannes
>

I have checked all patches with checkpatch, zero warnings.
Maybe only the cover letter has some style problems?


--
Thanks,
Victor.

2012-06-20 16:51:50

by Victor Goldenshtein

[permalink] [raw]
Subject: Re: [PATCH 0/7] nl/cfg/mac80211: add DFS master ability

On Wed, Jun 20, 2012 at 3:07 PM, Luciano Coelho <[email protected]> wrote:
> On Wed, 2012-06-20 at 15:03 +0300, Luciano Coelho wrote:
>> I guess the best thing to do is to keep basing mac80211 patches on top
>> of linux-wireless.
>
> I meant wireless-testing, of course.  (thanks Johannes for pointing
> out ;)
>

I will rebase to that one, thanks Luca.

--
Victor.

2012-06-19 08:42:30

by Victor Goldenshtein

[permalink] [raw]
Subject: Re: [PATCH 7/7] mac80211: add DFS support to monitor interface

On Tue, Jun 19, 2012 at 9:44 AM, Kalle Valo <[email protected]> wrote:
> On 06/18/2012 05:46 PM, Victor Goldenshtein wrote:
>> Stop dropping packets if we are on 'radar channel'
>> and the DFS is enabled/supported.
>>
>> Signed-off-by: Victor Goldenshtein <[email protected]>
>
> Why? I'm not very familiar with DFS so this change is not clear to me.
> You could write more about the reasoning in the commit log.

I will update the commit log message.

--
Thanks,
Victor.

2012-06-20 12:07:51

by Luciano Coelho

[permalink] [raw]
Subject: Re: [PATCH 0/7] nl/cfg/mac80211: add DFS master ability

On Wed, 2012-06-20 at 15:03 +0300, Luciano Coelho wrote:
> I guess the best thing to do is to keep basing mac80211 patches on top
> of linux-wireless.

I meant wireless-testing, of course. (thanks Johannes for pointing
out ;)


2012-06-19 06:57:11

by Luciano Coelho

[permalink] [raw]
Subject: Re: [PATCH 7/7] mac80211: add DFS support to monitor interface

On Tue, 2012-06-19 at 09:44 +0300, Kalle Valo wrote:
> On 06/18/2012 05:46 PM, Victor Goldenshtein wrote:
> > Stop dropping packets if we are on 'radar channel'
> > and the DFS is enabled/supported.
> >
> > Signed-off-by: Victor Goldenshtein <[email protected]>
>
> Why? I'm not very familiar with DFS so this change is not clear to me.

That's not a good excuse. :P

> You could write more about the reasoning in the commit log.

But I totally agree that the "why" is missing here. ;)

--
Luca.


2012-06-19 06:50:46

by Kalle Valo

[permalink] [raw]
Subject: Re: [PATCH 7/7] mac80211: add DFS support to monitor interface

On 06/18/2012 05:46 PM, Victor Goldenshtein wrote:
> Stop dropping packets if we are on 'radar channel'
> and the DFS is enabled/supported.
>
> Signed-off-by: Victor Goldenshtein <[email protected]>

Why? I'm not very familiar with DFS so this change is not clear to me.
You could write more about the reasoning in the commit log.

Kalle

2012-06-18 14:50:04

by Victor Goldenshtein

[permalink] [raw]
Subject: [PATCH 3/7] nl80211/cfg80211: add ability to enable TX on op-channel

The dfs master device should monitor radar channels
for potential radar interference for a minimum of
CAC (channel availability check) time, during this
period no tx can occur. If no radar interference
is detected the dfs master may initiate the tx with
new NL80211_CMD_DFS_ENABLE_TX command.

If this command is invoked prior performing a CAC or
the time passed sines the beginning of the CAC is
less than min CAC time (60 sec), -EPERM is returned.

Signed-off-by: Victor Goldenshtein <[email protected]>
---
include/linux/nl80211.h | 11 +++++++++++
include/net/cfg80211.h | 3 +++
net/wireless/nl80211.c | 36 ++++++++++++++++++++++++++++++++++++
3 files changed, 50 insertions(+), 0 deletions(-)

diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index ea6ce93..2f869a4 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -556,6 +556,15 @@
* @NL80211_CMD_RADAR_DETECT: Start radar detection in the driver/HW. Once
* radar detected usermode notified with this event.
*
+ * @NL80211_CMD_DFS_ENABLE_TX: Initiate tx after verifying radar clearness on
+ * dfs channel. The dfs master device should monitor radar channels
+ * for potential radar interference for a minimum of CAC (channel
+ * availability check) time, during this period no tx can occur. If no
+ * radar interference is detected during this period the dfs master may
+ * initiate the tx. If this command is invoked prior performing a CAC or
+ * the time passed sines the beginning of the CAC is less than
+ * NL80211_DFS_MIN_CAC_TIME_MS, -EPERM is returned.
+ *
* @NL80211_CMD_MAX: highest used command number
* @__NL80211_CMD_AFTER_LAST: internal use
*/
@@ -701,6 +710,8 @@ enum nl80211_commands {

NL80211_CMD_RADAR_DETECT,

+ NL80211_CMD_DFS_ENABLE_TX,
+
/* add new commands above here */

/* used to define NL80211_CMD_MAX below */
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 32dfc1f..030ed2f 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -1531,6 +1531,7 @@ struct cfg80211_gtk_rekey_data {
* See @ethtool_ops.get_strings
*
* @start_radar_detection: Start radar detection in the driver.
+ * @dfs_en_tx: Enable tx after radar interference check.
*/
struct cfg80211_ops {
int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
@@ -1740,6 +1741,8 @@ struct cfg80211_ops {
int (*start_radar_detection)(struct wiphy *wiphy,
struct net_device *dev,
struct ieee80211_channel *chan);
+ int (*dfs_en_tx)(struct wiphy *wiphy, struct net_device *dev,
+ struct ieee80211_channel *chan);
};

/*
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 573c966..eabe819 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -4273,6 +4273,34 @@ static int nl80211_start_radar_detection(struct sk_buff *skb,
return cfg80211_start_radar_detection(rdev, dev, chan);
}

+static int nl80211_dfs_en_tx(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];
+ bool dfs_supported = !!(rdev->wiphy.features & NL80211_FEATURE_DFS);
+ struct ieee80211_channel *chan;
+ int freq;
+
+ if (!rdev->ops->dfs_en_tx || !dfs_supported)
+ return -EOPNOTSUPP;
+
+ if (info->attrs[NL80211_ATTR_WIPHY_FREQ])
+ freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]);
+ else
+ return -EINVAL;
+
+ chan = ieee80211_get_channel(&rdev->wiphy, freq);
+ if (!chan)
+ return -EINVAL;
+
+ if ((!chan->radar_detect_timeout ||
+ time_is_after_jiffies(chan->radar_detect_timeout)) &&
+ (chan->flags & IEEE80211_CHAN_RADAR))
+ return -EPERM;
+
+ return rdev->ops->dfs_en_tx(&rdev->wiphy, dev, chan);
+}
+
static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb,
u32 seq, int flags,
struct cfg80211_registered_device *rdev,
@@ -7030,6 +7058,14 @@ static struct genl_ops nl80211_ops[] = {
.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
NL80211_FLAG_NEED_RTNL,
},
+ {
+ .cmd = NL80211_CMD_DFS_ENABLE_TX,
+ .doit = nl80211_dfs_en_tx,
+ .policy = nl80211_policy,
+ .flags = GENL_ADMIN_PERM,
+ .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
+ NL80211_FLAG_NEED_RTNL,
+ },

};

--
1.7.5.4


2012-06-18 14:49:55

by Victor Goldenshtein

[permalink] [raw]
Subject: [PATCH 2/7] mac80211: add radar detection command/event

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 <[email protected]>
---
include/net/mac80211.h | 17 +++++++++++++++++
net/mac80211/cfg.c | 16 ++++++++++++++++
net/mac80211/driver-ops.h | 14 ++++++++++++++
net/mac80211/driver-trace.h | 6 ++++++
net/mac80211/mlme.c | 8 ++++++++
5 files changed, 61 insertions(+), 0 deletions(-)

diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 95e39b6..a2222cf 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -2246,6 +2246,10 @@ enum ieee80211_rate_control_changed {
* @get_et_strings: Ethtool API to get a set of strings to describe stats
* and perhaps other supported types of ethtool data-sets.
*
+ * @start_radar_detection: Start radar detection on current operational
+ * channel, once started it will continuously monitor for radars as long
+ * as the channel active.
+ *
*/
struct ieee80211_ops {
void (*tx)(struct ieee80211_hw *hw, struct sk_buff *skb);
@@ -2385,6 +2389,9 @@ struct ieee80211_ops {
void (*get_et_strings)(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
u32 sset, u8 *data);
+ int (*start_radar_detection)(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_channel *chan);
};

/**
@@ -3557,6 +3564,16 @@ 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.
+ * @freq: frequency of the 'radar detected' channel.
+ * @gfp: context flags.
+ */
+void ieee80211_radar_detected(struct ieee80211_vif *vif, u16 freq, gfp_t gfp);
+
+/**
* ieee80211_get_operstate - get the operstate of the vif
*
* @vif: &struct ieee80211_vif pointer from the add_interface callback.
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 7d5108a..541b274 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -2211,6 +2211,21 @@ static int ieee80211_cancel_remain_on_channel(struct wiphy *wiphy,
return ieee80211_wk_cancel_remain_on_channel(sdata, cookie);
}

+static int ieee80211_start_radar_detection(struct wiphy *wiphy,
+ struct net_device *dev,
+ struct ieee80211_channel *chan)
+{
+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+ struct ieee80211_local *local = sdata->local;
+ int ret;
+
+ if (!local->ops->start_radar_detection)
+ return -EOPNOTSUPP;
+
+ ret = drv_start_radar_detection(local, sdata, chan);
+ return ret;
+}
+
static enum work_done_result
ieee80211_offchan_tx_done(struct ieee80211_work *wk, struct sk_buff *skb)
{
@@ -2979,4 +2994,5 @@ struct cfg80211_ops mac80211_config_ops = {
.get_et_sset_count = ieee80211_get_et_sset_count,
.get_et_stats = ieee80211_get_et_stats,
.get_et_strings = ieee80211_get_et_strings,
+ .start_radar_detection = ieee80211_start_radar_detection,
};
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index 6d33a0c..57185df 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -329,6 +329,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, sdata);
+ 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/driver-trace.h b/net/mac80211/driver-trace.h
index 6de00b2..4112aa3 100644
--- a/net/mac80211/driver-trace.h
+++ b/net/mac80211/driver-trace.h
@@ -484,6 +484,12 @@ DEFINE_EVENT(local_sdata_evt, drv_cancel_hw_scan,
TP_ARGS(local, sdata)
);

+DEFINE_EVENT(local_sdata_evt, drv_start_radar_detection,
+ TP_PROTO(struct ieee80211_local *local,
+ struct ieee80211_sub_if_data *sdata),
+ TP_ARGS(local, sdata)
+);
+
DEFINE_EVENT(local_sdata_evt, drv_sched_scan_start,
TP_PROTO(struct ieee80211_local *local,
struct ieee80211_sub_if_data *sdata),
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 66e4fcd..37ed827 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -3562,6 +3562,14 @@ void ieee80211_cqm_rssi_notify(struct ieee80211_vif *vif,
}
EXPORT_SYMBOL(ieee80211_cqm_rssi_notify);

+void ieee80211_radar_detected(struct ieee80211_vif *vif, u16 freq, gfp_t gfp)
+{
+ struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
+
+ cfg80211_radar_detected(sdata->dev, freq, gfp);
+}
+EXPORT_SYMBOL(ieee80211_radar_detected);
+
unsigned char ieee80211_get_operstate(struct ieee80211_vif *vif)
{
struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
--
1.7.5.4


2012-06-18 14:50:26

by Victor Goldenshtein

[permalink] [raw]
Subject: [PATCH 5/7] nl80211/cfg80211: add ap channel switch command/event

Add NL80211_CMD_AP_CHANNEL_SWITCH command/event
which triggers an AP channel switch process and
notifies usermode about channel switch complete
event, once it completed.

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 <[email protected]>
---
include/linux/nl80211.h | 25 ++++++++++++++
include/net/cfg80211.h | 17 +++++++++
net/wireless/mlme.c | 11 ++++++
net/wireless/nl80211.c | 84 +++++++++++++++++++++++++++++++++++++++++++++++
net/wireless/nl80211.h | 5 +++
5 files changed, 142 insertions(+), 0 deletions(-)

diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index 2f869a4..4279507 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -565,6 +565,15 @@
* the time passed sines the beginning of the CAC is less than
* NL80211_DFS_MIN_CAC_TIME_MS, -EPERM is returned.
*
+ * @NL80211_CMD_AP_CHANNEL_SWITCH: Perform a channel switch in the driver (for
+ * AP/GO).
+ * %NL80211_ATTR_WIPHY_FREQ: new channel frequency.
+ * %NL80211_ATTR_CH_SWITCH_BLOCK_TX: block tx on the current channel.
+ * %NL80211_ATTR_CH_SWITCH_POST_BLOCK_TX: block tx on the target channel.
+ * %NL80211_FREQ_ATTR_CH_SWITCH_COUNT: number of TBTT's until the channel
+ * switch event.
+ * This command will also notify about channel switch complete event.
+ *
* @NL80211_CMD_MAX: highest used command number
* @__NL80211_CMD_AFTER_LAST: internal use
*/
@@ -712,6 +721,8 @@ enum nl80211_commands {

NL80211_CMD_DFS_ENABLE_TX,

+ NL80211_CMD_AP_CHANNEL_SWITCH,
+
/* add new commands above here */

/* used to define NL80211_CMD_MAX below */
@@ -1238,6 +1249,14 @@ enum nl80211_commands {
* @NL80211_ATTR_BG_SCAN_PERIOD: Background scan period in seconds
* or 0 to disable background scan.
*
+ * @NL80211_ATTR_CH_SWITCH_COUNT: the number of TBTT's until the channel
+ * switch event
+ * @NL80211_ATTR_CH_SWITCH_BLOCK_TX: block tx on the current channel before the
+ * channel switch operation.
+ * @NL80211_ATTR_CH_SWITCH_POST_BLOCK_TX: block tx 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
*/
@@ -1489,6 +1508,10 @@ enum nl80211_attrs {

NL80211_ATTR_BG_SCAN_PERIOD,

+ 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,
@@ -2884,12 +2907,14 @@ enum nl80211_ap_sme_features {
* @NL80211_FEATURE_INACTIVITY_TIMER: This driver takes care of freeing up
* the connected inactive stations in AP mode.
* @NL80211_FEATURE_DFS: Radar detection is supported in the HW/driver.
+ * @NL80211_FEATURE_AP_CH_SWITCH: This driver supports AP channel switch.
*/
enum nl80211_feature_flags {
NL80211_FEATURE_SK_TX_STATUS = 1 << 0,
NL80211_FEATURE_HT_IBSS = 1 << 1,
NL80211_FEATURE_INACTIVITY_TIMER = 1 << 2,
NL80211_FEATURE_DFS = 1 << 3,
+ NL80211_FEATURE_AP_CH_SWITCH = 1 << 4,
};

/**
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 030ed2f..6eeae89 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -1532,6 +1532,8 @@ struct cfg80211_gtk_rekey_data {
*
* @start_radar_detection: Start radar detection in the driver.
* @dfs_en_tx: Enable tx after radar interference check.
+ *
+ * @ap_channel_switch: Perform a channel switch (for AP/GO).
*/
struct cfg80211_ops {
int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
@@ -1743,6 +1745,11 @@ struct cfg80211_ops {
struct ieee80211_channel *chan);
int (*dfs_en_tx)(struct wiphy *wiphy, struct net_device *dev,
struct ieee80211_channel *chan);
+
+ int (*ap_channel_switch)(struct wiphy *wiphy, struct net_device *dev,
+ u32 count, bool block_tx,
+ bool post_switch_block_tx,
+ struct ieee80211_channel *new_ch);
};

/*
@@ -3291,6 +3298,16 @@ void cfg80211_cqm_rssi_notify(struct net_device *dev,
void cfg80211_radar_detected(struct net_device *dev, u16 freq, gfp_t gfp);

/**
+ * cfg80211_ap_ch_switch_complete_notify - channel switch complete event
+ * @dev: network device
+ * @gfp: context flags
+ *
+ * Notify userspace about channel switch complete event.
+ */
+void cfg80211_ap_ch_switch_complete_notify(struct net_device *dev,
+ u16 freq, gfp_t gfp);
+
+/**
* cfg80211_cqm_pktloss_notify - notify userspace about packetloss to peer
* @dev: network device
* @peer: peer's MAC address
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
index a641db6..d45c875 100644
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
@@ -1018,3 +1018,14 @@ void cfg80211_radar_detected(struct net_device *dev, u16 freq, gfp_t gfp)
nl80211_radar_detected_notify(rdev, freq, dev, gfp);
}
EXPORT_SYMBOL(cfg80211_radar_detected);
+
+void cfg80211_ap_ch_switch_complete_notify(struct net_device *dev,
+ u16 freq, gfp_t gfp)
+{
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+ struct wiphy *wiphy = wdev->wiphy;
+ struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
+
+ nl80211_ap_ch_switch_complete_notify(rdev, freq, dev, gfp);
+}
+EXPORT_SYMBOL(cfg80211_ap_ch_switch_complete_notify);
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index eabe819..e6579bb 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -206,6 +206,9 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
[NL80211_ATTR_NOACK_MAP] = { .type = NLA_U16 },
[NL80211_ATTR_INACTIVITY_TIMEOUT] = { .type = NLA_U16 },
[NL80211_ATTR_BG_SCAN_PERIOD] = { .type = NLA_U16 },
+ [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 */
@@ -4301,6 +4304,42 @@ static int nl80211_dfs_en_tx(struct sk_buff *skb, struct genl_info *info)
return rdev->ops->dfs_en_tx(&rdev->wiphy, dev, chan);
}

+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];
+ u32 freq = 0, count = 0, post_switch_block_tx = 0, block_tx = 0;
+ struct ieee80211_channel *new_ch;
+
+ 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])
+ return -EINVAL;
+
+ count = nla_get_u32(info->attrs[NL80211_ATTR_CH_SWITCH_COUNT]);
+ freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]);
+
+ new_ch = ieee80211_get_channel(&rdev->wiphy, freq);
+ if (!new_ch || new_ch->flags & IEEE80211_CHAN_DISABLED)
+ return -EINVAL;
+
+ if (info->attrs[NL80211_ATTR_CH_SWITCH_BLOCK_TX])
+ block_tx = true;
+
+ if (info->attrs[NL80211_ATTR_CH_SWITCH_POST_BLOCK_TX])
+ post_switch_block_tx = true;
+
+ return rdev->ops->ap_channel_switch(&rdev->wiphy, dev, count, block_tx,
+ post_switch_block_tx, new_ch);
+}
+
static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb,
u32 seq, int flags,
struct cfg80211_registered_device *rdev,
@@ -7066,6 +7105,14 @@ static struct genl_ops nl80211_ops[] = {
.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
NL80211_FLAG_NEED_RTNL,
},
+ {
+ .cmd = NL80211_CMD_AP_CHANNEL_SWITCH,
+ .doit = nl80211_ap_channel_switch,
+ .policy = nl80211_policy,
+ .flags = GENL_ADMIN_PERM,
+ .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
+ NL80211_FLAG_NEED_RTNL,
+ },

};

@@ -8206,6 +8253,43 @@ nl80211_radar_detected_notify(struct cfg80211_registered_device *rdev,
}

void
+nl80211_ap_ch_switch_complete_notify(struct cfg80211_registered_device *rdev,
+ u16 freq, 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_AP_CHANNEL_SWITCH);
+ 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, 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 a333261..aca0de3 100644
--- a/net/wireless/nl80211.h
+++ b/net/wireless/nl80211.h
@@ -111,6 +111,11 @@ nl80211_radar_detected_notify(struct cfg80211_registered_device *rdev,
u16 freq, struct net_device *netdev, gfp_t gfp);

void
+nl80211_ap_ch_switch_complete_notify(struct cfg80211_registered_device *rdev,
+ u16 freq, 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,
u32 num_packets, gfp_t gfp);
--
1.7.5.4


2012-06-20 10:34:31

by Zefir Kurtisi

[permalink] [raw]
Subject: Re: [PATCH 0/7] nl/cfg/mac80211: add DFS master ability

On 06/18/2012 04:46 PM, Victor Goldenshtein wrote:
> In continuation to proposed RFC, this patch set (with hostap patch series) adds support for DFS (Dynamic Frequency Selection) according 802.11h.
>
> [...]

Thanks for the updated patches, Victor.

Going to test them by preparing the ath9k interface.

Right now they do not apply on top of wireless-testing, could you please
rebase? Thanks.