2012-08-08 12:00:19

by Victor Goldenshtein

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

v3:

Rebased to "wireless-testing".


nl80211/cfg80211: add radar detection command/event
Added units documentation to "radar_detect_timeout".
Added "cac_type" - which indicates that CAC is started for this channel type.
Added NL80211_ATTR_WIPHY_CHANNEL_TYPE.
Fixed merge problem.
Removed "!!" in nl80211_start_radar_detection.
Return -EBUSY in start_radar_detection if detection already started for this specific channel.


mac80211: add radar detection command/event
Added tracer to ieee80211_radar_detected().
Changed freq argument in ieee80211_radar_detected() to "struct ieee80211_channel *chan"
Reset CAC during interface down.


nl80211/cfg80211: add ability to enable TX on op-channel
Removed "!!" in nl80211_dfs_en_tx().
Typo fix in the documentation.
Added additional check to validate that we're on NL80211_CHAN_HT20 channel, otherwise return -EPERM.


nl80211/cfg80211: add ap channel switch command/event
Moved struct ieee80211_ap_ch_switch from mac to cfg + pass it as argument in ap_channel_switch()
Add "if (ch_type != NL80211_CHAN_NO_HT) return -EOPNOTSUPP"
Changed freq argument in ap_ch_switch_complete_notify() to "struct ieee80211_channel *chan"


mac80211: add ap channel switch command/event
Renamed ieee80211_ap_ch_switch_complete_notify to ieee80211_ap_ch_switch_done.
Removed the freq argument in ieee80211_ap_ch_switch_done().
Save the target channel in new "local->next_ap_channel" and update the operational channel in ieee80211_ap_ch_switch_done.
Add tracer to ieee80211_ap_ch_switch_done().
Updated commit log message.
Added sanity checks in ap_channel_switch() + ieee80211_ap_ch_switch_complete


mac80211: add DFS support to monitor interface
Removed "!!" in ieee80211_monitor_start_xmit().

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
mac80211: add ap channel switch command/event
mac80211: add DFS support to monitor interface

include/linux/nl80211.h | 42 +++++++++++
include/net/cfg80211.h | 63 +++++++++++++++++
include/net/mac80211.h | 37 ++++++++++
net/mac80211/cfg.c | 50 +++++++++++++
net/mac80211/driver-ops.h | 38 ++++++++++
net/mac80211/iface.c | 7 ++
net/mac80211/main.c | 3 +
net/mac80211/mlme.c | 32 +++++++++
net/mac80211/trace.h | 87 +++++++++++++++++++++++
net/mac80211/tx.c | 13 ++--
net/wireless/core.h | 4 +
net/wireless/mlme.c | 38 ++++++++++
net/wireless/nl80211.c | 171 +++++++++++++++++++++++++++++++++++++++++++++
net/wireless/nl80211.h | 6 ++
14 files changed, 585 insertions(+), 6 deletions(-)

--
1.7.5.4



2012-08-08 12:00:37

by Victor Goldenshtein

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

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 <[email protected]>
---
include/linux/nl80211.h | 24 ++++++++++++++++++++
include/net/cfg80211.h | 34 +++++++++++++++++++++++++++++
net/wireless/nl80211.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 113 insertions(+), 0 deletions(-)

diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index 6c2884c..5a193b3 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -565,6 +565,14 @@
* %NL80211_ATTR_IFINDEX is now on %NL80211_ATTR_WIPHY_FREQ with
* %NL80211_ATTR_WIPHY_CHANNEL_TYPE.
*
+ * @NL80211_CMD_AP_CH_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.
+ *
* @NL80211_CMD_RADAR_DETECT: Start radar detection in the driver/HW. Once
* radar detected usermode notified with this event.
*
@@ -720,6 +728,8 @@ enum nl80211_commands {

NL80211_CMD_CH_SWITCH_NOTIFY,

+ NL80211_CMD_AP_CH_SWITCH,
+
NL80211_CMD_RADAR_DETECT,

NL80211_CMD_DFS_ENABLE_TX,
@@ -1267,6 +1277,14 @@ enum nl80211_commands {
* was used to provide the hint. For the different types of
* allowed user regulatory hints see nl80211_user_reg_hint_type.
*
+ * @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
*/
@@ -1522,6 +1540,10 @@ enum nl80211_attrs {

NL80211_ATTR_USER_REG_HINT_TYPE,

+ 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,
@@ -3011,6 +3033,7 @@ enum nl80211_ap_sme_features {
* to work properly to suppport receiving regulatory hints from
* cellular base stations.
* @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,
@@ -3018,6 +3041,7 @@ enum nl80211_feature_flags {
NL80211_FEATURE_INACTIVITY_TIMER = 1 << 2,
NL80211_FEATURE_CELL_BASE_REG_HINTS = 1 << 3,
NL80211_FEATURE_DFS = 1 << 4,
+ NL80211_FEATURE_AP_CH_SWITCH = 1 << 5,
};

/**
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 3a56601..66c8c9b 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -153,6 +153,34 @@ struct ieee80211_channel {
};

/**
+ * 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, 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
+ * @channel_type: the type of the new channel
+ * @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 ieee80211_channel *channel;
+ enum nl80211_channel_type channel_type;
+ u8 count;
+};
+
+/**
* enum ieee80211_rate_flags - rate flags
*
* Hardware/specification flags for rates. These are structured
@@ -1629,6 +1657,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 AP channel switch.
*/
struct cfg80211_ops {
int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
@@ -1852,6 +1882,10 @@ struct cfg80211_ops {

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,
+ struct ieee80211_ap_ch_switch *ap_ch_sw);
};

/*
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 869d271..14d05d0 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -355,6 +355,9 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
[NL80211_ATTR_BG_SCAN_PERIOD] = { .type = NLA_U16 },
[NL80211_ATTR_WDEV] = { .type = NLA_U64 },
[NL80211_ATTR_USER_REG_HINT_TYPE] = { .type = NLA_U32 },
+ [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 */
@@ -4644,6 +4647,50 @@ 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;
+ struct ieee80211_ap_ch_switch ap_ch_sw;
+
+ 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));
+
+ ap_ch_sw.channel_type =
+ nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]);
+ if (ap_ch_sw.channel_type != NL80211_CHAN_HT20)
+ return -EOPNOTSUPP;
+
+ ap_ch_sw.count = nla_get_u32(info->attrs[NL80211_ATTR_CH_SWITCH_COUNT]);
+ freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]);
+
+ ap_ch_sw.channel = ieee80211_get_channel(&rdev->wiphy, freq);
+ if (!ap_ch_sw.channel ||
+ ap_ch_sw.channel->flags & IEEE80211_CHAN_DISABLED)
+ return -EINVAL;
+
+ 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,
@@ -7518,6 +7565,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,
+ },

};

--
1.7.5.4


2012-08-10 16:28:27

by Stanislaw Gruszka

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

On Wed, Aug 08, 2012 at 02:53:38PM +0300, Victor Goldenshtein wrote:
> --- a/include/net/mac80211.h
> +++ b/include/net/mac80211.h
> @@ -2262,6 +2262,10 @@ enum ieee80211_rate_control_changed {
> * The callback will be called before each transmission and upon return
> * mac80211 will transmit the frame right away.
> * The callback is optional and can (should!) 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.
> */
> struct ieee80211_ops {
> void (*tx)(struct ieee80211_hw *hw, struct sk_buff *skb);
> @@ -2404,6 +2408,10 @@ struct ieee80211_ops {
>
> void (*mgd_prepare_tx)(struct ieee80211_hw *hw,
> struct ieee80211_vif *vif);
> +
> + int (*start_radar_detection)(struct ieee80211_hw *hw,
> + struct ieee80211_vif *vif,
> + struct ieee80211_channel *chan);

Why we need new callback? I.e. why this can be done by ->config ?

Stanislaw

2012-08-09 11:51:39

by Stanislaw Gruszka

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

On Wed, Aug 08, 2012 at 02:53:37PM +0300, Victor Goldenshtein wrote:
> + cac_type = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]);
> + if (cac_type != NL80211_CHAN_HT20)
> + return -EOPNOTSUPP;
Since only HT20 is supported, what for we have this variable?

Stanislaw

2012-08-08 12:00:27

by Victor Goldenshtein

[permalink] [raw]
Subject: [PATCH v3 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 since 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 | 5 +++++
net/wireless/nl80211.c | 36 ++++++++++++++++++++++++++++++++++++
3 files changed, 52 insertions(+), 0 deletions(-)

diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index 773ba68..6c2884c 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -568,6 +568,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 since 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
*/
@@ -713,6 +722,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 c40a05d..3a56601 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -1627,6 +1627,8 @@ struct cfg80211_gtk_rekey_data {
* current monitoring channel.
*
* @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);
@@ -1847,6 +1849,9 @@ 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 74e65d7..869d271 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -4616,6 +4616,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->cac_type != NL80211_CHAN_HT20) ||
+ 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,
@@ -7482,6 +7510,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-08-08 12:00:48

by Victor Goldenshtein

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

AP mode uses monitor interfaces to transmit
management frames which were blocked for "radar
channels" until now.

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

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

diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index acf712f..d1b6f9a 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -1583,6 +1583,7 @@ 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
@@ -1595,13 +1596,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-08-09 12:09:00

by Victor Goldenshtein

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

On Thu, Aug 9, 2012 at 2:51 PM, Stanislaw Gruszka <[email protected]> wrote:
> On Wed, Aug 08, 2012 at 02:53:37PM +0300, Victor Goldenshtein wrote:
>> + cac_type = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]);
>> + if (cac_type != NL80211_CHAN_HT20)
>> + return -EOPNOTSUPP;
> Since only HT20 is supported, what for we have this variable?
>

Security measures and preparation for future HT40.

--
Thanks,
Victor.

2012-08-13 07:37:00

by Stanislaw Gruszka

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

On Sun, Aug 12, 2012 at 10:31:40AM +0300, Goldenshtein, Victor wrote:
> On Fri, Aug 10, 2012 at 7:28 PM, Stanislaw Gruszka <[email protected]> wrote:
> > On Wed, Aug 08, 2012 at 02:53:38PM +0300, Victor Goldenshtein wrote:
> >> --- a/include/net/mac80211.h
> >> +++ b/include/net/mac80211.h
> >> @@ -2262,6 +2262,10 @@ enum ieee80211_rate_control_changed {
> >> * The callback will be called before each transmission and upon return
> >> * mac80211 will transmit the frame right away.
> >> * The callback is optional and can (should!) 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.
> >> */
> >> struct ieee80211_ops {
> >> void (*tx)(struct ieee80211_hw *hw, struct sk_buff *skb);
> >> @@ -2404,6 +2408,10 @@ struct ieee80211_ops {
> >>
> >> void (*mgd_prepare_tx)(struct ieee80211_hw *hw,
> >> struct ieee80211_vif *vif);
> >> +
> >> + int (*start_radar_detection)(struct ieee80211_hw *hw,
> >> + struct ieee80211_vif *vif,
> >> + struct ieee80211_channel *chan);
> >
> > Why we need new callback? I.e. why this can be done by ->config ?
> >
>
> See proposed RFC and previous threads.

I can not find mail where this is explained, could you please provide
link.

Stanislaw

2012-08-08 12:00:19

by Victor Goldenshtein

[permalink] [raw]
Subject: [PATCH v3 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 | 24 ++++++++++++++
net/wireless/core.h | 4 ++
net/wireless/mlme.c | 38 ++++++++++++++++++++++
net/wireless/nl80211.c | 80 +++++++++++++++++++++++++++++++++++++++++++++++
net/wireless/nl80211.h | 6 +++
6 files changed, 159 insertions(+), 0 deletions(-)

diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index 2f38788..773ba68 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -565,6 +565,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
*/
@@ -708,6 +711,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 */
@@ -2994,12 +2999,14 @@ enum nl80211_ap_sme_features {
* @NL80211_FEATURE_CELL_BASE_REG_HINTS: This driver has been tested
* to work properly to suppport receiving regulatory hints from
* cellular base stations.
+ * @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_CELL_BASE_REG_HINTS = 1 << 3,
+ NL80211_FEATURE_DFS = 1 << 4,
};

/**
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 3d254e1..c40a05d 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -131,6 +131,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;
@@ -143,6 +148,8 @@ 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;
};

/**
@@ -1618,6 +1625,8 @@ struct cfg80211_gtk_rekey_data {
* @get_channel: Get the current operating channel for the virtual interface.
* For monitor interfaces, it should return %NULL unless there's a single
* current monitoring channel.
+ *
+ * @start_radar_detection: Start radar detection in the driver.
*/
struct cfg80211_ops {
int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
@@ -1834,6 +1843,10 @@ struct cfg80211_ops {
(*get_channel)(struct wiphy *wiphy,
struct wireless_dev *wdev,
enum nl80211_channel_type *type);
+
+ int (*start_radar_detection)(struct wiphy *wiphy,
+ struct net_device *dev,
+ struct ieee80211_channel *chan);
};

/*
@@ -3392,6 +3405,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/net/wireless/core.h b/net/wireless/core.h
index bc7430b..06d8609 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -471,6 +471,10 @@ rdev_freq_to_chan(struct cfg80211_registered_device *rdev,
int cfg80211_set_monitor_channel(struct cfg80211_registered_device *rdev,
int freq, enum nl80211_channel_type chantype);

+int cfg80211_start_radar_detection(struct cfg80211_registered_device *rdev,
+ struct net_device *dev,
+ struct ieee80211_channel *chan);
+
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 1cdb1d5..6530af3 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;
@@ -1006,3 +1008,39 @@ 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;
+ chan->cac_type = 0;
+ }
+
+ return err;
+}
+
+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->radar_detect_timeout = 0;
+ chan->cac_type = 0;
+
+ 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 97026f3..74e65d7 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -4581,6 +4581,41 @@ 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;
+ enum nl80211_channel_type cac_type;
+
+ if (!dfs_supported)
+ return -EOPNOTSUPP;
+
+ if (!info->attrs[NL80211_ATTR_WIPHY_FREQ] ||
+ !info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE])
+ return -EINVAL;
+
+ cac_type = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]);
+ if (cac_type != NL80211_CHAN_HT20)
+ return -EOPNOTSUPP;
+
+ 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;
+
+ if (chan->cac_type)
+ return -EBUSY;
+
+ chan->cac_type = cac_type;
+
+ 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,
@@ -7439,6 +7474,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,
+ },

};

@@ -8602,6 +8645,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 9f2616f..e4b6d1a 100644
--- a/net/wireless/nl80211.h
+++ b/net/wireless/nl80211.h
@@ -105,6 +105,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.5.4


2012-08-10 16:36:59

by Stanislaw Gruszka

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

On Wed, Aug 08, 2012 at 02:53:42PM +0300, Victor Goldenshtein wrote:
> void (*channel_switch)(struct ieee80211_hw *hw,
> struct ieee80211_channel_switch *ch_switch);
> + void (*ap_channel_switch)(struct ieee80211_hw *hw,
> + struct ieee80211_ap_ch_switch *ap_ch_switch);

Why we can not use ->channel_switch calback for this purpose (merge
ieee80211_channel_switch and ieee80211_ap_ch_switch)?

> +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->channel_switch)
> + return -EOPNOTSUPP;

Probably you want to check local->ops->ap_channel_switch.

Stanislaw

2012-08-12 07:31:41

by Victor Goldenshtein

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

On Fri, Aug 10, 2012 at 7:28 PM, Stanislaw Gruszka <[email protected]> wrote:
> On Wed, Aug 08, 2012 at 02:53:38PM +0300, Victor Goldenshtein wrote:
>> --- a/include/net/mac80211.h
>> +++ b/include/net/mac80211.h
>> @@ -2262,6 +2262,10 @@ enum ieee80211_rate_control_changed {
>> * The callback will be called before each transmission and upon return
>> * mac80211 will transmit the frame right away.
>> * The callback is optional and can (should!) 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.
>> */
>> struct ieee80211_ops {
>> void (*tx)(struct ieee80211_hw *hw, struct sk_buff *skb);
>> @@ -2404,6 +2408,10 @@ struct ieee80211_ops {
>>
>> void (*mgd_prepare_tx)(struct ieee80211_hw *hw,
>> struct ieee80211_vif *vif);
>> +
>> + int (*start_radar_detection)(struct ieee80211_hw *hw,
>> + struct ieee80211_vif *vif,
>> + struct ieee80211_channel *chan);
>
> Why we need new callback? I.e. why this can be done by ->config ?
>

See proposed RFC and previous threads.

--
Thanks,
Victor.

2012-08-08 12:00:32

by Victor Goldenshtein

[permalink] [raw]
Subject: [PATCH v3 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/trace.h | 6 ++++++
4 files changed, 39 insertions(+), 0 deletions(-)

diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index d29c99a..ecdfb6a 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -2266,6 +2266,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 {
void (*tx)(struct ieee80211_hw *hw, struct sk_buff *skb);
@@ -2412,6 +2414,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 59b7ffe..eb18868 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -2418,6 +2418,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 int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
struct ieee80211_channel *chan, bool offchan,
enum nl80211_channel_type channel_type,
@@ -3091,4 +3105,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,
+ .dfs_en_tx = ieee80211_dfs_en_tx,
};
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index 0f42502..04a9168 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -335,6 +335,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/trace.h b/net/mac80211/trace.h
index acc5b0a..2ef4731 100644
--- a/net/mac80211/trace.h
+++ b/net/mac80211/trace.h
@@ -492,6 +492,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-08-10 16:26:06

by Stanislaw Gruszka

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

On Thu, Aug 09, 2012 at 03:08:59PM +0300, Goldenshtein, Victor wrote:
> On Thu, Aug 9, 2012 at 2:51 PM, Stanislaw Gruszka <[email protected]> wrote:
> > On Wed, Aug 08, 2012 at 02:53:37PM +0300, Victor Goldenshtein wrote:
> >> + cac_type = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]);
> >> + if (cac_type != NL80211_CHAN_HT20)
> >> + return -EOPNOTSUPP;
> > Since only HT20 is supported, what for we have this variable?
> >
>
> Security measures and preparation for future HT40.

I dislike "preparation for future" thing. We have lot of stuff like
that in kernel, which never get implemented, and only mess up the code.

How near future is that?

Also what about pure, non HT, channels?

Stanislaw

2012-08-08 12:00:47

by Victor Goldenshtein

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

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 <[email protected]>
---
include/net/mac80211.h | 14 ++++++++++++
net/mac80211/cfg.c | 19 ++++++++++++++++
net/mac80211/driver-ops.h | 10 ++++++++
net/mac80211/main.c | 3 ++
net/mac80211/mlme.c | 21 +++++++++++++++++
net/mac80211/trace.h | 53 +++++++++++++++++++++++++++++++++++++++++++++
6 files changed, 120 insertions(+), 0 deletions(-)

diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index ecdfb6a..3cefafa 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -2368,6 +2368,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_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);
@@ -3599,6 +3601,18 @@ void ieee80211_radar_detected(struct ieee80211_vif *vif,
struct ieee80211_channel *chan, gfp_t gfp);

/**
+ * 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 ieee80211_channel *new_channel,
+ enum nl80211_channel_type type);
+
+/**
* 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 eb18868..5dbc17a 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -2432,6 +2432,24 @@ 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,
+ 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->channel_switch)
+ return -EOPNOTSUPP;
+
+ if (!ap_ch_switch || !ap_ch_switch->channel)
+ return -EINVAL;
+
+ 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,
enum nl80211_channel_type channel_type,
@@ -3106,4 +3124,5 @@ struct cfg80211_ops mac80211_config_ops = {
.get_channel = ieee80211_cfg_get_channel,
.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 04a9168..e22149e 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -703,6 +703,16 @@ 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_ch_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/main.c b/net/mac80211/main.c
index c26e231..df985b2 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -577,6 +577,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 2d87c5b..d1de8f1 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -3560,3 +3560,24 @@ 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_done(struct ieee80211_vif *vif,
+ struct ieee80211_channel *new_channel,
+ enum nl80211_channel_type type)
+{
+ 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;
+
+ /* update the device channel directly */
+ mutex_lock(&local->mtx);
+ local->oper_channel = local->hw.conf.channel = new_channel;
+ local->_oper_channel_type = type;
+ mutex_unlock(&local->mtx);
+
+ cfg80211_ch_switch_notify(sdata->dev, new_channel->center_freq, type);
+ trace_api_ap_ch_switch_done(sdata, new_channel->center_freq);
+}
+EXPORT_SYMBOL(ieee80211_ap_ch_switch_done);
diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h
index 2ef4731..d9de352 100644
--- a/net/mac80211/trace.h
+++ b/net/mac80211/trace.h
@@ -929,6 +929,37 @@ TRACE_EVENT(drv_channel_switch,
)
);

+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
+ __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),

@@ -1422,6 +1453,28 @@ TRACE_EVENT(api_cqm_rssi_notify,
)
);

+TRACE_EVENT(api_ap_ch_switch_done,
+ 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 " switched to new freq:%d",
+ VIF_PR_ARG, __entry->center_freq
+ )
+)
+
TRACE_EVENT(api_radar_detected,
TP_PROTO(struct ieee80211_sub_if_data *sdata,
u16 center_freq),
--
1.7.5.4


2012-08-08 12:00:22

by Victor Goldenshtein

[permalink] [raw]
Subject: [PATCH v3 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 | 19 +++++++++++++++++++
net/mac80211/cfg.c | 16 ++++++++++++++++
net/mac80211/driver-ops.h | 14 ++++++++++++++
net/mac80211/iface.c | 7 +++++++
net/mac80211/mlme.c | 11 +++++++++++
net/mac80211/trace.h | 28 ++++++++++++++++++++++++++++
6 files changed, 95 insertions(+), 0 deletions(-)

diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index bb86aa6..d29c99a 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -2262,6 +2262,10 @@ enum ieee80211_rate_control_changed {
* The callback will be called before each transmission and upon return
* mac80211 will transmit the frame right away.
* The callback is optional and can (should!) 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.
*/
struct ieee80211_ops {
void (*tx)(struct ieee80211_hw *hw, struct sk_buff *skb);
@@ -2404,6 +2408,10 @@ struct ieee80211_ops {

void (*mgd_prepare_tx)(struct ieee80211_hw *hw,
struct ieee80211_vif *vif);
+
+ int (*start_radar_detection)(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_channel *chan);
};

/**
@@ -3576,6 +3584,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 d41974a..59b7ffe 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -2403,6 +2403,21 @@ 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 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 int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
struct ieee80211_channel *chan, bool offchan,
enum nl80211_channel_type channel_type,
@@ -3075,4 +3090,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 df92031..0f42502 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -321,6 +321,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/iface.c b/net/mac80211/iface.c
index bfb57dc..ca7e4c2 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -731,6 +731,13 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
/* free all potentially still buffered bcast frames */
local->total_ps_buffered -= skb_queue_len(&sdata->u.ap.ps_bc_buf);
skb_queue_purge(&sdata->u.ap.ps_bc_buf);
+
+ /* reset DFS channel availability check */
+ if (local->oper_channel && sdata->wdev.preset_chan) {
+ local->oper_channel->cac_type = 0;
+ /* in case AP hasn't started yet */
+ sdata->wdev.preset_chan->cac_type = 0;
+ }
} 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 a4a5acd..2d87c5b 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -3549,3 +3549,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 c6d33b5..acc5b0a 100644
--- a/net/mac80211/trace.h
+++ b/net/mac80211/trace.h
@@ -486,6 +486,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),
@@ -1410,6 +1416,28 @@ TRACE_EVENT(api_cqm_rssi_notify,
)
);

+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(api_scan_completed,
TP_PROTO(struct ieee80211_local *local, bool aborted),

--
1.7.5.4


2012-08-12 07:31:25

by Victor Goldenshtein

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

> Also what about pure, non HT, channels?
>

Can't think on any reason why we can't support the non HT channels,
the whole point here is the bandwidth.
So, will add them too.

--
Thanks,
Victor.

2012-08-20 10:32:29

by Johannes Berg

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

On Mon, 2012-08-13 at 09:34 +0200, Stanislaw Gruszka wrote:
> On Sun, Aug 12, 2012 at 10:31:29AM +0300, Goldenshtein, Victor wrote:
> > > Why we can not use ->channel_switch calback for this purpose (merge
> > > ieee80211_channel_switch and ieee80211_ap_ch_switch)?
> > >
> >
> > Well at first (see previous threads) it was a single channel switch
> > for both AP/STA, but later after community reviews it was decided to
> > split these two.
>
> Ah, ok. Although I do not see the point of creating almost two identical
> structures and two identical callbacks, this is up to Johannes.

Mostly the point is that the behaviour is really different in terms of
who control it and how. E.g. the timing is not synchronised, etc. In
fact I'm not even sure the timing here is done by the device? Although
it really should be I guess.

johannes


2012-08-12 07:31:31

by Victor Goldenshtein

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

> Why we can not use ->channel_switch calback for this purpose (merge
> ieee80211_channel_switch and ieee80211_ap_ch_switch)?
>

Well at first (see previous threads) it was a single channel switch
for both AP/STA, but later after community reviews it was decided to
split these two.

>> +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->channel_switch)
>> + return -EOPNOTSUPP;
>
> Probably you want to check local->ops->ap_channel_switch.
>

This is the evidence ;).
Good catch and thanks for reviewing.

--
Victor.

2012-08-20 07:21:06

by Victor Goldenshtein

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

On Mon, Aug 13, 2012 at 10:36 AM, Stanislaw Gruszka <[email protected]> wrote:
> On Sun, Aug 12, 2012 at 10:31:40AM +0300, Goldenshtein, Victor wrote:
>> On Fri, Aug 10, 2012 at 7:28 PM, Stanislaw Gruszka <[email protected]> wrote:
>> > On Wed, Aug 08, 2012 at 02:53:38PM +0300, Victor Goldenshtein wrote:
>> >> --- a/include/net/mac80211.h
>> >> +++ b/include/net/mac80211.h
>> >> @@ -2262,6 +2262,10 @@ enum ieee80211_rate_control_changed {
>> >> * The callback will be called before each transmission and upon return
>> >> * mac80211 will transmit the frame right away.
>> >> * The callback is optional and can (should!) 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.
>> >> */
>> >> struct ieee80211_ops {
>> >> void (*tx)(struct ieee80211_hw *hw, struct sk_buff *skb);
>> >> @@ -2404,6 +2408,10 @@ struct ieee80211_ops {
>> >>
>> >> void (*mgd_prepare_tx)(struct ieee80211_hw *hw,
>> >> struct ieee80211_vif *vif);
>> >> +
>> >> + int (*start_radar_detection)(struct ieee80211_hw *hw,
>> >> + struct ieee80211_vif *vif,
>> >> + struct ieee80211_channel *chan);
>> >
>> > Why we need new callback? I.e. why this can be done by ->config ?
>> >
>>
>> See proposed RFC and previous threads.
>
> I can not find mail where this is explained, could you please provide
> link.
>

http://article.gmane.org/gmane.linux.kernel.wireless.general/83760/match=

--
Victor.

2012-08-13 07:35:26

by Stanislaw Gruszka

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

On Sun, Aug 12, 2012 at 10:31:29AM +0300, Goldenshtein, Victor wrote:
> > Why we can not use ->channel_switch calback for this purpose (merge
> > ieee80211_channel_switch and ieee80211_ap_ch_switch)?
> >
>
> Well at first (see previous threads) it was a single channel switch
> for both AP/STA, but later after community reviews it was decided to
> split these two.

Ah, ok. Although I do not see the point of creating almost two identical
structures and two identical callbacks, this is up to Johannes.

Stanislaw

2012-08-20 10:33:17

by Johannes Berg

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

On Fri, 2012-08-10 at 18:25 +0200, Stanislaw Gruszka wrote:
> On Thu, Aug 09, 2012 at 03:08:59PM +0300, Goldenshtein, Victor wrote:
> > On Thu, Aug 9, 2012 at 2:51 PM, Stanislaw Gruszka <[email protected]> wrote:
> > > On Wed, Aug 08, 2012 at 02:53:37PM +0300, Victor Goldenshtein wrote:
> > >> + cac_type = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]);
> > >> + if (cac_type != NL80211_CHAN_HT20)
> > >> + return -EOPNOTSUPP;
> > > Since only HT20 is supported, what for we have this variable?
> > >
> >
> > Security measures and preparation for future HT40.
>
> I dislike "preparation for future" thing. We have lot of stuff like
> that in kernel, which never get implemented, and only mess up the code.
>
> How near future is that?

Well, it doesn't really matter -- if you allow specifying the channel
type then you have to validate it in some way, otherwise one could
assume it works with 40 MHz, right?

johannes


2012-09-10 11:25:00

by Johannes Berg

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


> +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->channel_switch)
> + return -EOPNOTSUPP;
> +
> + if (!ap_ch_switch || !ap_ch_switch->channel)
> + return -EINVAL;
> +
> + drv_ap_channel_switch(local, ap_ch_switch);
> + return 0;

errors are not possible?

> +void ieee80211_ap_ch_switch_done(struct ieee80211_vif *vif,
> + struct ieee80211_channel *new_channel,
> + enum nl80211_channel_type type)
> +{
> + 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;
> +
> + /* update the device channel directly */
> + mutex_lock(&local->mtx);
> + local->oper_channel = local->hw.conf.channel = new_channel;
> + local->_oper_channel_type = type;
> + mutex_unlock(&local->mtx);
> +
> + cfg80211_ch_switch_notify(sdata->dev, new_channel->center_freq, type);
> + trace_api_ap_ch_switch_done(sdata, new_channel->center_freq);

tracing last seems very strange

johannes


2012-09-10 10:53:53

by Johannes Berg

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

On Mon, 2012-08-20 at 10:21 +0300, Goldenshtein, Victor wrote:
> On Mon, Aug 13, 2012 at 10:36 AM, Stanislaw Gruszka <[email protected]> wrote:
> > On Sun, Aug 12, 2012 at 10:31:40AM +0300, Goldenshtein, Victor wrote:
> >> On Fri, Aug 10, 2012 at 7:28 PM, Stanislaw Gruszka <[email protected]> wrote:
> >> > On Wed, Aug 08, 2012 at 02:53:38PM +0300, Victor Goldenshtein wrote:
> >> >> --- a/include/net/mac80211.h
> >> >> +++ b/include/net/mac80211.h
> >> >> @@ -2262,6 +2262,10 @@ enum ieee80211_rate_control_changed {
> >> >> * The callback will be called before each transmission and upon return
> >> >> * mac80211 will transmit the frame right away.
> >> >> * The callback is optional and can (should!) 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.
> >> >> */
> >> >> struct ieee80211_ops {
> >> >> void (*tx)(struct ieee80211_hw *hw, struct sk_buff *skb);
> >> >> @@ -2404,6 +2408,10 @@ struct ieee80211_ops {
> >> >>
> >> >> void (*mgd_prepare_tx)(struct ieee80211_hw *hw,
> >> >> struct ieee80211_vif *vif);
> >> >> +
> >> >> + int (*start_radar_detection)(struct ieee80211_hw *hw,
> >> >> + struct ieee80211_vif *vif,
> >> >> + struct ieee80211_channel *chan);
> >> >
> >> > Why we need new callback? I.e. why this can be done by ->config ?
> >> >
> >>
> >> See proposed RFC and previous threads.
> >
> > I can not find mail where this is explained, could you please provide
> > link.
> >
>
> http://article.gmane.org/gmane.linux.kernel.wireless.general/83760/match=

Well, that doesn't really explain it, but I do think that it's easier
for drivers to implement as a separate callback and we can then also
tell whether it's supported or not.

johannes


2012-09-10 10:52:41

by Johannes Berg

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

On Wed, 2012-08-08 at 14:53 +0300, Victor Goldenshtein wrote:

> + * @NL80211_FEATURE_DFS: Radar detection is supported in the HW/driver.

How will you know what kind of radar detection is supported? That is, HT
20, HT 40, in the future VHT80/160/80+80?

> + int (*start_radar_detection)(struct wiphy *wiphy,
> + struct net_device *dev,
> + struct ieee80211_channel *chan);

Channel type/bandwidth might be needed?

> +void cfg80211_radar_detected(struct net_device *dev,
> + struct ieee80211_channel *chan, gfp_t gfp);

Is the channel parameter useful? Only one detection can be triggered at
any given time.

> void cfg80211_send_rx_auth(struct net_device *dev, const u8 *buf, size_t len)
> {
> struct wireless_dev *wdev = dev->ieee80211_ptr;
> @@ -1006,3 +1008,39 @@ 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;
> + chan->cac_type = 0;
> + }

You're not setting cac_type in the good case, and also
radar_detect_timeout can actually be 0 in the good case due to jiffies
wrap. How is that handled?

> + chan->cac_type = 0;

Also here and above you should use channel type enums. In fact, 0 is
"NOHT". Oops. Need a boolean I guess that indicates validity.

> + bool dfs_supported = (rdev->wiphy.features & NL80211_FEATURE_DFS);

why bother with the variable?

> + if (!chan || !(chan->flags & IEEE80211_CHAN_RADAR))
> + return -EINVAL;
> +
> + if (chan->cac_type)
> + return -EBUSY;
> +
> + chan->cac_type = cac_type;

Aha. But these things probably should be in the function:

> + return cfg80211_start_radar_detection(rdev, dev, chan);

so it's actually a potentially useful function for other places.
Otherwise you could just manually inline it here, I see no issues with
that either.

johannes


2012-09-10 11:16:57

by Johannes Berg

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

On Wed, 2012-08-08 at 14:53 +0300, Victor Goldenshtein wrote:
> 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.

> + if (!local->ops->start_radar_detection)
> + return -EOPNOTSUPP;
> +
> + ret = drv_start_radar_detection(local, sdata, chan);
> + return ret;

Remove the ret variable please.

> +++ b/net/mac80211/iface.c
> @@ -731,6 +731,13 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
> /* free all potentially still buffered bcast frames */
> local->total_ps_buffered -= skb_queue_len(&sdata->u.ap.ps_bc_buf);
> skb_queue_purge(&sdata->u.ap.ps_bc_buf);
> +
> + /* reset DFS channel availability check */
> + if (local->oper_channel && sdata->wdev.preset_chan) {
> + local->oper_channel->cac_type = 0;
> + /* in case AP hasn't started yet */
> + sdata->wdev.preset_chan->cac_type = 0;
> + }

Why is mac80211 modifying cfg80211 fields? cfg80211 also uses this, no?
This seems strange to me.

> +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)
> +);

Umm, parameters?

johannes


2012-09-07 15:47:23

by Simon Wunderlich

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

Hello,

what is the status of this patchset? There have not been any major change
requests, nor promises to send a revised patchset. On the other hand it
hast not yet been merged into wireless testing.

Can anyone give us a status update? Maybe I'm missing something ... :)

Thanks,
Simon


On Wed, Aug 08, 2012 at 02:53:36PM +0300, Victor Goldenshtein wrote:
> v3:
>
> Rebased to "wireless-testing".
>
>
> nl80211/cfg80211: add radar detection command/event
> Added units documentation to "radar_detect_timeout".
> Added "cac_type" - which indicates that CAC is started for this channel type.
> Added NL80211_ATTR_WIPHY_CHANNEL_TYPE.
> Fixed merge problem.
> Removed "!!" in nl80211_start_radar_detection.
> Return -EBUSY in start_radar_detection if detection already started for this specific channel.
>
>
> mac80211: add radar detection command/event
> Added tracer to ieee80211_radar_detected().
> Changed freq argument in ieee80211_radar_detected() to "struct ieee80211_channel *chan"
> Reset CAC during interface down.
>
>
> nl80211/cfg80211: add ability to enable TX on op-channel
> Removed "!!" in nl80211_dfs_en_tx().
> Typo fix in the documentation.
> Added additional check to validate that we're on NL80211_CHAN_HT20 channel, otherwise return -EPERM.
>
>
> nl80211/cfg80211: add ap channel switch command/event
> Moved struct ieee80211_ap_ch_switch from mac to cfg + pass it as argument in ap_channel_switch()
> Add "if (ch_type != NL80211_CHAN_NO_HT) return -EOPNOTSUPP"
> Changed freq argument in ap_ch_switch_complete_notify() to "struct ieee80211_channel *chan"
>
>
> mac80211: add ap channel switch command/event
> Renamed ieee80211_ap_ch_switch_complete_notify to ieee80211_ap_ch_switch_done.
> Removed the freq argument in ieee80211_ap_ch_switch_done().
> Save the target channel in new "local->next_ap_channel" and update the operational channel in ieee80211_ap_ch_switch_done.
> Add tracer to ieee80211_ap_ch_switch_done().
> Updated commit log message.
> Added sanity checks in ap_channel_switch() + ieee80211_ap_ch_switch_complete
>
>
> mac80211: add DFS support to monitor interface
> Removed "!!" in ieee80211_monitor_start_xmit().
>
> 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
> mac80211: add ap channel switch command/event
> mac80211: add DFS support to monitor interface
>
> include/linux/nl80211.h | 42 +++++++++++
> include/net/cfg80211.h | 63 +++++++++++++++++
> include/net/mac80211.h | 37 ++++++++++
> net/mac80211/cfg.c | 50 +++++++++++++
> net/mac80211/driver-ops.h | 38 ++++++++++
> net/mac80211/iface.c | 7 ++
> net/mac80211/main.c | 3 +
> net/mac80211/mlme.c | 32 +++++++++
> net/mac80211/trace.h | 87 +++++++++++++++++++++++
> net/mac80211/tx.c | 13 ++--
> net/wireless/core.h | 4 +
> net/wireless/mlme.c | 38 ++++++++++
> net/wireless/nl80211.c | 171 +++++++++++++++++++++++++++++++++++++++++++++
> net/wireless/nl80211.h | 6 ++
> 14 files changed, 585 insertions(+), 6 deletions(-)
>
> --
> 1.7.5.4
>
>


Attachments:
(No filename) (3.29 kB)
signature.asc (198.00 B)
Digital signature
Download all attachments

2012-09-07 16:04:01

by Johannes Berg

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

On Fri, 2012-09-07 at 17:47 +0200, Simon Wunderlich wrote:
> Hello,
>
> what is the status of this patchset? There have not been any major change
> requests, nor promises to send a revised patchset. On the other hand it
> hast not yet been merged into wireless testing.
>
> Can anyone give us a status update? Maybe I'm missing something ... :)

I promised a review but then forgot, it seems. Sorry about that.

johannes


2012-09-10 11:23:11

by Johannes Berg

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


> + * @NL80211_CMD_AP_CH_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.

Needs more documentation.

> @@ -720,6 +728,8 @@ enum nl80211_commands {
>
> NL80211_CMD_CH_SWITCH_NOTIFY,
>
> + NL80211_CMD_AP_CH_SWITCH,
> +
> NL80211_CMD_RADAR_DETECT,
>
> NL80211_CMD_DFS_ENABLE_TX,

Ahem.

> @@ -1267,6 +1277,14 @@ enum nl80211_commands {
> * was used to provide the hint. For the different types of
> * allowed user regulatory hints see nl80211_user_reg_hint_type.
> *
> + * @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.

Need to document the types.

> * @NL80211_FEATURE_DFS: Radar detection is supported in the HW/driver.
> + * @NL80211_FEATURE_AP_CH_SWITCH: This driver supports AP channel switch.

I have a nagging feeling I keep asking this, but what's the point of
radar detection without channel switch? Or is it the other way around
that's interesting? Maybe should verify that if you have DFS you also
have chanswitch?

> /**
> + * 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, 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
> + * @channel_type: the type of the new channel
> + * @count: the number of TBTT's until the channel switch event
> + */

Bogus documentation.

johannes


2012-09-10 11:20:08

by Johannes Berg

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

On Wed, 2012-08-08 at 14:53 +0300, Victor Goldenshtein wrote:
> 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/trace.h | 6 ++++++
> 4 files changed, 39 insertions(+), 0 deletions(-)
>
> diff --git a/include/net/mac80211.h b/include/net/mac80211.h
> index d29c99a..ecdfb6a 100644
> --- a/include/net/mac80211.h
> +++ b/include/net/mac80211.h
> @@ -2266,6 +2266,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.

Please also document (for both!) the fact that they can sleep.


> +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)
> +);

Again, parameters.

johannes


2012-09-10 11:25:25

by Johannes Berg

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

On Wed, 2012-08-08 at 14:53 +0300, Victor Goldenshtein wrote:
> AP mode uses monitor interfaces to transmit
> management frames which were blocked for "radar
> channels" until now.
>
> Stop dropping packets if we are on 'radar channel'
> and the DFS is enabled.

Umm, no? Check for dfs_en_tx().

johannes


2012-10-09 18:42:21

by Johannes Berg

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

On Wed, 2012-10-03 at 15:54 +0200, Goldenshtein, Victor wrote:
> On Mon, Sep 10, 2012 at 2:26 PM, Johannes Berg
> <[email protected]> wrote:
> > On Wed, 2012-08-08 at 14:53 +0300, Victor Goldenshtein wrote:
> >> AP mode uses monitor interfaces to transmit
> >> management frames which were blocked for "radar
> >> channels" until now.
> >>
> >> Stop dropping packets if we are on 'radar channel'
> >> and the DFS is enabled.
> >
> > Umm, no? Check for dfs_en_tx().
> >
>
> no need, the AP is started only after the dfs_en_tx().

but this is on monitor mode, no? and monitor mode isn't used just for
AP. In fact, AP no longer even uses monitor mode, so you don't need this
at all since you should be working with a new hostapd version that will
get the DFS feature ... and then you're working on a current version
that already no longer uses monitor mode for DFS. Both kernel & hostapd
have to be new enough, so monitor mode won't be used...

johannes


2012-10-03 13:53:58

by Victor Goldenshtein

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

On Mon, Sep 10, 2012 at 2:23 PM, Johannes Berg
<[email protected]> wrote:
>
>> + * @NL80211_CMD_AP_CH_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.
>
> Needs more documentation.

I'll elaborate a bit..

>
>> @@ -720,6 +728,8 @@ enum nl80211_commands {
>>
>> NL80211_CMD_CH_SWITCH_NOTIFY,
>>
>> + NL80211_CMD_AP_CH_SWITCH,
>> +
>> NL80211_CMD_RADAR_DETECT,
>>
>> NL80211_CMD_DFS_ENABLE_TX,
>
> Ahem.
>

just thought to put the channel switch stuff together.
don't might to move it down.

>> @@ -1267,6 +1277,14 @@ enum nl80211_commands {
>> * was used to provide the hint. For the different types of
>> * allowed user regulatory hints see nl80211_user_reg_hint_type.
>> *
>> + * @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.
>
> Need to document the types.

np.

>
>> * @NL80211_FEATURE_DFS: Radar detection is supported in the HW/driver.
>> + * @NL80211_FEATURE_AP_CH_SWITCH: This driver supports AP channel switch.
>
> I have a nagging feeling I keep asking this, but what's the point of
> radar detection without channel switch? Or is it the other way around
> that's interesting? Maybe should verify that if you have DFS you also
> have chanswitch?

one might support a channel switch without DFS, but the one who sets
the "NL80211_FEATURE_DFS" must support channel switch.
I don't might to check both these flags, but then I think it would be
cleaner (more readable) to leave the "dfs_supported" flag.
something like:
bool dfs_supported = ((local->hw.wiphy->features & NL80211_FEATURE_DFS) &&
(local->hw.wiphy->features & NL80211_FEATURE_AP_CH_SWITCH));


>
>> /**
>> + * 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, 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
>> + * @channel_type: the type of the new channel
>> + * @count: the number of TBTT's until the channel switch event
>> + */
>
> Bogus documentation.

can you please elaborate on this one.
note that it's almost identical to "ieee80211_channel_switch" struct,
the two new parameters here are "post_switch_block_tx" and
"channel_type".

--
Thanks,
Victor.

2012-10-14 13:35:11

by Victor Goldenshtein

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

On 10/09/2012 08:44 PM, Johannes Berg wrote:
>>>> + * @block_tx: Indicates whether transmission must be blocked before the
>>>> + * scheduled channel switch, as indicated by the AP.
>
>>> Bogus documentation.
>>
>> can you please elaborate on this one.
>
> for example the only thing I quoted above now ... clearly can't be right
>
>> note that it's almost identical to "ieee80211_channel_switch" struct,
>
> and that's the problem

now I see ;)
will fix the documentation in next v4 series.


--
Thanks,
Victor.

2012-10-03 13:54:01

by Victor Goldenshtein

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

On Mon, Sep 10, 2012 at 2:25 PM, Johannes Berg
<[email protected]> wrote:
>
>> +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->channel_switch)
>> + return -EOPNOTSUPP;
>> +
>> + if (!ap_ch_switch || !ap_ch_switch->channel)
>> + return -EINVAL;
>> +
>> + drv_ap_channel_switch(local, ap_ch_switch);
>> + return 0;
>
> errors are not possible?
>

driver is not allowed to fail here.

>> +void ieee80211_ap_ch_switch_done(struct ieee80211_vif *vif,
>> + struct ieee80211_channel *new_channel,
>> + enum nl80211_channel_type type)
>> +{
>> + 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;
>> +
>> + /* update the device channel directly */
>> + mutex_lock(&local->mtx);
>> + local->oper_channel = local->hw.conf.channel = new_channel;
>> + local->_oper_channel_type = type;
>> + mutex_unlock(&local->mtx);
>> +
>> + cfg80211_ch_switch_notify(sdata->dev, new_channel->center_freq, type);
>> + trace_api_ap_ch_switch_done(sdata, new_channel->center_freq);
>
> tracing last seems very strange
>

will reorder.

--
Thanks,
Victor.

2012-10-09 18:46:22

by Johannes Berg

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

On Wed, 2012-10-03 at 15:53 +0200, Goldenshtein, Victor wrote:

> >> + * @NL80211_FEATURE_DFS: Radar detection is supported in the HW/driver.
> >
> > How will you know what kind of radar detection is supported? That is, HT
> > 20, HT 40, in the future VHT80/160/80+80?
> >
>
> only 20 Mhz is supported at first stage, do you prefer to rename it to
> something like: NL80211_FEATURE_20MHZ_DFS

no idea, maybe that, or maybe have some other field that lists the
channel widths that are supported?

> >> +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;
> >> + chan->cac_type = 0;
> >> + }
> >
> > You're not setting cac_type in the good case, and also
> > radar_detect_timeout can actually be 0 in the good case due to jiffies
> > wrap. How is that handled?
> >
>
> I'm using time_is_after_jiffies() in nl80211_dfs_en_tx() which AFAIK
> can handle jiffies wrap.

yeah but if you need to set radar_detect_timeout=0 here, then it looks
like you're also using the 0 value as a special value to indicate
"nothing in progress"?


> right, since NOHT is 0 we probably need additional flag something like
> "chan->cac_started"

yes

> alternatively we can add "__NL80211_CHAN_INVALID" at index 0 to the
> enum nl80211_channel_type.

no
nl80211 is abi :)

johannes


2012-10-04 15:42:15

by Victor Goldenshtein

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

On Wed, Oct 3, 2012 at 3:54 PM, Goldenshtein, Victor <[email protected]> wrote:
> On Mon, Sep 10, 2012 at 2:25 PM, Johannes Berg
> <[email protected]> wrote:
>>
>>> +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->channel_switch)
>>> + return -EOPNOTSUPP;
>>> +
>>> + if (!ap_ch_switch || !ap_ch_switch->channel)
>>> + return -EINVAL;
>>> +
>>> + drv_ap_channel_switch(local, ap_ch_switch);
>>> + return 0;
>>
>> errors are not possible?
>>
>
> driver is not allowed to fail here.
>
on second thought ;) can't see why we can't propagate driver's return
value to userspace, which will deal with the error code.

--
Thanks,
Victor.

2012-10-03 13:53:54

by Victor Goldenshtein

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

On Mon, Sep 10, 2012 at 2:20 PM, Johannes Berg
<[email protected]> wrote:
> On Wed, 2012-08-08 at 14:53 +0300, Victor Goldenshtein wrote:
>> 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/trace.h | 6 ++++++
>> 4 files changed, 39 insertions(+), 0 deletions(-)
>>
>> diff --git a/include/net/mac80211.h b/include/net/mac80211.h
>> index d29c99a..ecdfb6a 100644
>> --- a/include/net/mac80211.h
>> +++ b/include/net/mac80211.h
>> @@ -2266,6 +2266,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.
>
> Please also document (for both!) the fact that they can sleep.
>

ok.

>
>> +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)
>> +);
>
> Again, parameters.
>

will add channel frequency.

--
Thanks,
Victor.

2012-10-09 18:43:59

by Johannes Berg

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

On Wed, 2012-10-03 at 15:53 +0200, Goldenshtein, Victor wrote:
> >> @@ -720,6 +728,8 @@ enum nl80211_commands {
> >>
> >> NL80211_CMD_CH_SWITCH_NOTIFY,
> >>
> >> + NL80211_CMD_AP_CH_SWITCH,
> >> +
> >> NL80211_CMD_RADAR_DETECT,
> >>
> >> NL80211_CMD_DFS_ENABLE_TX,
> >
> > Ahem.
> >
>
> just thought to put the channel switch stuff together.
> don't might to move it down.

Yeah but you can *never* insert anything in the middle.


> >> * @NL80211_FEATURE_DFS: Radar detection is supported in the HW/driver.
> >> + * @NL80211_FEATURE_AP_CH_SWITCH: This driver supports AP channel switch.
> >
> > I have a nagging feeling I keep asking this, but what's the point of
> > radar detection without channel switch? Or is it the other way around
> > that's interesting? Maybe should verify that if you have DFS you also
> > have chanswitch?
>
> one might support a channel switch without DFS, but the one who sets
> the "NL80211_FEATURE_DFS" must support channel switch.
> I don't might to check both these flags, but then I think it would be
> cleaner (more readable) to leave the "dfs_supported" flag.
> something like:
> bool dfs_supported = ((local->hw.wiphy->features & NL80211_FEATURE_DFS) &&
> (local->hw.wiphy->features & NL80211_FEATURE_AP_CH_SWITCH));


fair enough. makes sense for p2p I guess

> >> + * @block_tx: Indicates whether transmission must be blocked before the
> >> + * scheduled channel switch, as indicated by the AP.

> > Bogus documentation.
>
> can you please elaborate on this one.

for example the only thing I quoted above now ... clearly can't be right

> note that it's almost identical to "ieee80211_channel_switch" struct,

and that's the problem

johannes


2012-10-03 13:54:07

by Victor Goldenshtein

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

On Mon, Sep 10, 2012 at 2:26 PM, Johannes Berg
<[email protected]> wrote:
> On Wed, 2012-08-08 at 14:53 +0300, Victor Goldenshtein wrote:
>> AP mode uses monitor interfaces to transmit
>> management frames which were blocked for "radar
>> channels" until now.
>>
>> Stop dropping packets if we are on 'radar channel'
>> and the DFS is enabled.
>
> Umm, no? Check for dfs_en_tx().
>

no need, the AP is started only after the dfs_en_tx().

--
Thanks,
Victor.

2012-10-03 13:53:51

by Victor Goldenshtein

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

On Mon, Sep 10, 2012 at 2:17 PM, Johannes Berg
<[email protected]> wrote:
> On Wed, 2012-08-08 at 14:53 +0300, Victor Goldenshtein wrote:
>> 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.
>
>> + if (!local->ops->start_radar_detection)
>> + return -EOPNOTSUPP;
>> +
>> + ret = drv_start_radar_detection(local, sdata, chan);
>> + return ret;
>
> Remove the ret variable please.
>

ok.

>> +++ b/net/mac80211/iface.c
>> @@ -731,6 +731,13 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
>> /* free all potentially still buffered bcast frames */
>> local->total_ps_buffered -= skb_queue_len(&sdata->u.ap.ps_bc_buf);
>> skb_queue_purge(&sdata->u.ap.ps_bc_buf);
>> +
>> + /* reset DFS channel availability check */
>> + if (local->oper_channel && sdata->wdev.preset_chan) {
>> + local->oper_channel->cac_type = 0;
>> + /* in case AP hasn't started yet */
>> + sdata->wdev.preset_chan->cac_type = 0;
>> + }
>
> Why is mac80211 modifying cfg80211 fields? cfg80211 also uses this, no?
> This seems strange to me.
>
I will remove the "...preset_chan->cac_type = 0;" line.
We can reset the "preset_chan->cac_type" (or the new cac_started flag)
in __nl80211_set_channel().

>> +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)
>> +);
>
> Umm, parameters?
>

will add here also the channel frequency.

--
Thanks,
Victor.

2012-10-14 13:35:11

by Victor Goldenshtein

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

On 10/09/2012 08:42 PM, Johannes Berg wrote:
> On Wed, 2012-10-03 at 15:54 +0200, Goldenshtein, Victor wrote:
>> On Mon, Sep 10, 2012 at 2:26 PM, Johannes Berg
>> <[email protected]> wrote:
>>> On Wed, 2012-08-08 at 14:53 +0300, Victor Goldenshtein wrote:
>>>> AP mode uses monitor interfaces to transmit
>>>> management frames which were blocked for "radar
>>>> channels" until now.
>>>>
>>>> Stop dropping packets if we are on 'radar channel'
>>>> and the DFS is enabled.
>>>
>>> Umm, no? Check for dfs_en_tx().
>>>
>>
>> no need, the AP is started only after the dfs_en_tx().
>
> but this is on monitor mode, no? and monitor mode isn't used just for
> AP. In fact, AP no longer even uses monitor mode, so you don't need this
> at all since you should be working with a new hostapd version that will
> get the DFS feature ... and then you're working on a current version
> that already no longer uses monitor mode for DFS. Both kernel & hostapd
> have to be new enough, so monitor mode won't be used...
>

right, this patch here from the days AP used monitor mode.
I"ll remove it.


--
Thanks,
Victor.

2012-10-03 13:53:47

by Victor Goldenshtein

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

Thanks for the review and sorry for the delayed response.

On Mon, Sep 10, 2012 at 1:53 PM, Johannes Berg
<[email protected]> wrote:
> On Wed, 2012-08-08 at 14:53 +0300, Victor Goldenshtein wrote:
>
>> + * @NL80211_FEATURE_DFS: Radar detection is supported in the HW/driver.
>
> How will you know what kind of radar detection is supported? That is, HT
> 20, HT 40, in the future VHT80/160/80+80?
>

only 20 Mhz is supported at first stage, do you prefer to rename it to
something like: NL80211_FEATURE_20MHZ_DFS

>> + int (*start_radar_detection)(struct wiphy *wiphy,
>> + struct net_device *dev,
>> + struct ieee80211_channel *chan);
>
> Channel type/bandwidth might be needed?
>

np, will add also the channel type here.

>> +void cfg80211_radar_detected(struct net_device *dev,
>> + struct ieee80211_channel *chan, gfp_t gfp);
>
> Is the channel parameter useful? Only one detection can be triggered at
> any given time.

yes, for MC platforms and for sanity checks.

>
>> void cfg80211_send_rx_auth(struct net_device *dev, const u8 *buf, size_t len)
>> {
>> struct wireless_dev *wdev = dev->ieee80211_ptr;
>> @@ -1006,3 +1008,39 @@ 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;
>> + chan->cac_type = 0;
>> + }
>
> You're not setting cac_type in the good case, and also
> radar_detect_timeout can actually be 0 in the good case due to jiffies
> wrap. How is that handled?
>

I'm using time_is_after_jiffies() in nl80211_dfs_en_tx() which AFAIK
can handle jiffies wrap.

>> + chan->cac_type = 0;
>
> Also here and above you should use channel type enums. In fact, 0 is
> "NOHT". Oops. Need a boolean I guess that indicates validity.
>

right, since NOHT is 0 we probably need additional flag something like
"chan->cac_started"
alternatively we can add "__NL80211_CHAN_INVALID" at index 0 to the
enum nl80211_channel_type.

>> + bool dfs_supported = (rdev->wiphy.features & NL80211_FEATURE_DFS);
>
> why bother with the variable?
>

IMHO in that way the if expression is shorter and more readable.

>> + if (!chan || !(chan->flags & IEEE80211_CHAN_RADAR))
>> + return -EINVAL;
>> +
>> + if (chan->cac_type)
>> + return -EBUSY;
>> +
>> + chan->cac_type = cac_type;
>
> Aha. But these things probably should be in the function:
>
>> + return cfg80211_start_radar_detection(rdev, dev, chan);
>
> so it's actually a potentially useful function for other places.
> Otherwise you could just manually inline it here, I see no issues with
> that either.
>

will manually inline cfg80211_start_radar_detection() into
nl80211_start_radar_detection().

--
Thanks,
Victor.

2012-10-14 13:35:22

by Victor Goldenshtein

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

On 10/09/2012 08:46 PM, Johannes Berg wrote:
> yeah but if you need to set radar_detect_timeout=0 here, then it looks
> like you're also using the 0 value as a special value to indicate
> "nothing in progress"?
>
We agreed to use "chan->cac_started" flag for that purpose, so there is
no need to reset "radar_detect_timeout" I will remove it.


--
Thanks,
Victor.