2012-05-24 18:55:32

by Victor Goldenshtein

[permalink] [raw]
Subject: [PATCH 1/2] nl80211/cfg80211: add scan channel times to scan command

In order to give the usermode an ability to configure
scan channel times, and as it required for the beacon
reports in the 802.11k standard.

Add to the scan command min/max channel times. Add
min/max passive channel times, since a single scan
can contain both passive and active channels due to
regulatory constraints.

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

diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index 2540e86..8dca611 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -1222,6 +1222,23 @@ enum nl80211_commands {
* @NL80211_ATTR_BG_SCAN_PERIOD: Background scan period in seconds
* or 0 to disable background scan.
*
+ * @NL80211_ATTR_SCAN_MIN_CH_TIME: Minimum active scan time (in TUs),
+ * u32 attribute to setup minimum time to wait on each channel, if received
+ * at least one probe_resp/beacon during this period will continue waiting
+ * @NL80211_ATTR_SCAN_MAX_CH_TIME, otherwise will move to next channel.
+ * @NL80211_ATTR_SCAN_MAX_CH_TIME: Maximum active scan time (in TUs),
+ * u32 attribute to setup maximum time to wait on the channel.
+ * @NL80211_ATTR_SCAN_PSV_MIN_CH_TIME: Minimum passive scan time (in TUs),
+ * u32 attribute (similar to @NL80211_ATTR_SCAN_MIN_CH_TIME).
+ * @NL80211_ATTR_SCAN_PSV_MAX_CH_TIME: Maximum passive scan time (in TUs),
+ * u32 attribute (similar to @NL80211_ATTR_SCAN_MAX_CH_TIME).
+ * Note:
+ * The above channel time attributes are for the %NL80211_CMD_TRIGGER_SCAN
+ * command. The attributes are optional, the driver will use default
+ * channel time values if the attribute is not set or set to zero.
+ * If one of the min times will be greater than max, -EINVAL will be
+ * returned. For the software scan only the min times are relevant.
+ *
* @NL80211_ATTR_MAX: highest attribute number currently defined
* @__NL80211_ATTR_AFTER_LAST: internal use
*/
@@ -1473,6 +1490,11 @@ enum nl80211_attrs {

NL80211_ATTR_BG_SCAN_PERIOD,

+ NL80211_ATTR_SCAN_MIN_CH_TIME,
+ NL80211_ATTR_SCAN_MAX_CH_TIME,
+ NL80211_ATTR_SCAN_PSV_MIN_CH_TIME,
+ NL80211_ATTR_SCAN_PSV_MAX_CH_TIME,
+
/* add attributes here, update the policy in nl80211.c */

__NL80211_ATTR_AFTER_LAST,
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index adb2320..948cf60 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -920,6 +920,12 @@ struct cfg80211_ssid {
* @dev: the interface
* @aborted: (internal) scan request was notified as aborted
* @no_cck: used to send probe requests at non CCK rate in 2GHz band
+ * @min_ch_time: minimum time to wait on each channel for active scans
+ * @max_ch_time: maximum time to wait on each channel for active scans
+ * @min_passive_ch_time: minimum time to wait on each channel for passive scans
+ * @max_passive_ch_time: maximum time to wait on each channel for passive scans
+ * Note: If the above channel times are not set or set to zero, the default
+ * channel times will be used.
*/
struct cfg80211_scan_request {
struct cfg80211_ssid *ssids;
@@ -936,6 +942,11 @@ struct cfg80211_scan_request {
bool aborted;
bool no_cck;

+ u32 min_ch_time;
+ u32 max_ch_time;
+ u32 min_passive_ch_time;
+ u32 max_passive_ch_time;
+
/* keep last */
struct ieee80211_channel *channels[0];
};
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 859bd66..4ac8fed 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -206,6 +206,10 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
[NL80211_ATTR_NOACK_MAP] = { .type = NLA_U16 },
[NL80211_ATTR_INACTIVITY_TIMEOUT] = { .type = NLA_U16 },
[NL80211_ATTR_BG_SCAN_PERIOD] = { .type = NLA_U16 },
+ [NL80211_ATTR_SCAN_MIN_CH_TIME] = { .type = NLA_U32 },
+ [NL80211_ATTR_SCAN_MAX_CH_TIME] = { .type = NLA_U32 },
+ [NL80211_ATTR_SCAN_PSV_MIN_CH_TIME] = { .type = NLA_U32 },
+ [NL80211_ATTR_SCAN_PSV_MAX_CH_TIME] = { .type = NLA_U32 },
};

/* policy for the key attributes */
@@ -3884,6 +3888,27 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
request->ie_len);
}

+ if (info->attrs[NL80211_ATTR_SCAN_MIN_CH_TIME]) {
+ request->min_ch_time =
+ nla_get_u32(info->attrs[NL80211_ATTR_SCAN_MIN_CH_TIME]);
+ }
+ if (info->attrs[NL80211_ATTR_SCAN_MAX_CH_TIME]) {
+ request->max_ch_time =
+ nla_get_u32(info->attrs[NL80211_ATTR_SCAN_MAX_CH_TIME]);
+ if (request->min_ch_time > request->max_ch_time)
+ return -EINVAL;
+ }
+ if (info->attrs[NL80211_ATTR_SCAN_PSV_MIN_CH_TIME]) {
+ request->min_passive_ch_time =
+ nla_get_u32(info->attrs[NL80211_ATTR_SCAN_PSV_MIN_CH_TIME]);
+ }
+ if (info->attrs[NL80211_ATTR_SCAN_PSV_MAX_CH_TIME]) {
+ request->max_passive_ch_time =
+ nla_get_u32(info->attrs[NL80211_ATTR_SCAN_PSV_MAX_CH_TIME]);
+ if (request->min_passive_ch_time > request->max_passive_ch_time)
+ return -EINVAL;
+ }
+
for (i = 0; i < IEEE80211_NUM_BANDS; i++)
if (wiphy->bands[i])
request->rates[i] =
--
1.7.5.4



2012-05-24 18:55:34

by Victor Goldenshtein

[permalink] [raw]
Subject: [PATCH 2/2] mac80211: handle channel times in scan command

Use the user scan times if those were set, otherwise
use the default values.

This patch handles both hw_scan and non-offload scan.

Signed-off-by: Victor Goldenshtein <[email protected]>
---
net/mac80211/scan.c | 34 +++++++++++++++++++++++++---------
1 files changed, 25 insertions(+), 9 deletions(-)

diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index 8282284..0757551 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -421,7 +421,7 @@ static void ieee80211_scan_state_send_probe(struct ieee80211_local *local,
* After sending probe requests, wait for probe responses
* on the channel.
*/
- *next_delay = IEEE80211_CHANNEL_TIME;
+ *next_delay = local->scan_req->min_ch_time;
local->next_scan_state = SCAN_DECISION;
}

@@ -456,6 +456,13 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,

local->hw_scan_req->ssids = req->ssids;
local->hw_scan_req->n_ssids = req->n_ssids;
+ local->hw_scan_req->max_ch_time = req->max_ch_time;
+ local->hw_scan_req->min_ch_time = req->min_ch_time;
+ local->hw_scan_req->max_passive_ch_time =
+ req->max_passive_ch_time;
+ local->hw_scan_req->min_passive_ch_time =
+ req->min_passive_ch_time;
+
ies = (u8 *)local->hw_scan_req +
sizeof(*local->hw_scan_req) +
req->n_channels * sizeof(req->channels[0]);
@@ -475,6 +482,12 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
local->scan_req = req;
local->scan_sdata = sdata;

+ if (!local->scan_req->min_passive_ch_time)
+ local->scan_req->min_passive_ch_time =
+ IEEE80211_PASSIVE_CHANNEL_TIME;
+ if (!local->scan_req->min_ch_time)
+ local->scan_req->min_ch_time = IEEE80211_CHANNEL_TIME;
+
if (local->ops->hw_scan) {
__set_bit(SCAN_HW_SCANNING, &local->scanning);
} else if ((req->n_channels == 1) &&
@@ -502,10 +515,10 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
if ((req->channels[0]->flags &
IEEE80211_CHAN_PASSIVE_SCAN) ||
!local->scan_req->n_ssids) {
- next_delay = IEEE80211_PASSIVE_CHANNEL_TIME;
+ next_delay = local->scan_req->min_passive_ch_time;
} else {
ieee80211_scan_state_send_probe(local, &next_delay);
- next_delay = IEEE80211_CHANNEL_TIME;
+ next_delay = local->scan_req->min_ch_time;
}

/* Now, just wait a bit and we are all done! */
@@ -540,15 +553,16 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
}

static unsigned long
-ieee80211_scan_get_channel_time(struct ieee80211_channel *chan)
+ieee80211_scan_get_channel_time(struct cfg80211_scan_request *scan_req,
+ struct ieee80211_channel *chan)
{
/*
* TODO: channel switching also consumes quite some time,
* add that delay as well to get a better estimation
*/
if (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN)
- return IEEE80211_PASSIVE_CHANNEL_TIME;
- return IEEE80211_PROBE_DELAY + IEEE80211_CHANNEL_TIME;
+ return scan_req->min_passive_ch_time;
+ return IEEE80211_PROBE_DELAY + scan_req->min_ch_time;
}

static void ieee80211_scan_state_decision(struct ieee80211_local *local,
@@ -609,12 +623,14 @@ static void ieee80211_scan_state_decision(struct ieee80211_local *local,
*/

bad_latency = time_after(jiffies +
- ieee80211_scan_get_channel_time(next_chan),
+ ieee80211_scan_get_channel_time(local->scan_req,
+ next_chan),
local->leave_oper_channel_time +
usecs_to_jiffies(pm_qos_request(PM_QOS_NETWORK_LATENCY)));

listen_int_exceeded = time_after(jiffies +
- ieee80211_scan_get_channel_time(next_chan),
+ ieee80211_scan_get_channel_time(local->scan_req,
+ next_chan),
local->leave_oper_channel_time +
usecs_to_jiffies(min_beacon_int * 1024) *
local->hw.conf.listen_interval);
@@ -662,7 +678,7 @@ static void ieee80211_scan_state_set_channel(struct ieee80211_local *local,
*/
if (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN ||
!local->scan_req->n_ssids) {
- *next_delay = IEEE80211_PASSIVE_CHANNEL_TIME;
+ *next_delay = local->scan_req->min_passive_ch_time;
local->next_scan_state = SCAN_DECISION;
return;
}
--
1.7.5.4


2012-05-29 07:10:16

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH 2/2] mac80211: handle channel times in scan command

On Thu, 2012-05-24 at 21:52 +0300, Victor Goldenshtein wrote:
> Use the user scan times if those were set, otherwise
> use the default values.

I'd prefer the default values to be defined in cfg80211, not mac80211,
so that other drivers can also benefit once they add support for these
settings.

johannes


2012-05-29 14:35:49

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH 2/2] mac80211: handle channel times in scan command

On Tue, 2012-05-29 at 17:28 +0300, Goldenshtein, Victor wrote:
> On Tue, May 29, 2012 at 10:10 AM, Johannes Berg
> <[email protected]> wrote:
> > I'd prefer the default values to be defined in cfg80211, not mac80211,
> > so that other drivers can also benefit once they add support for these
> > settings.
> >
>
> you mean, to move (and rename) the:
>
> #define IEEE80211_CHANNEL_TIME (HZ / 33)
> #define IEEE80211_PASSIVE_CHANNEL_TIME (HZ / 8)
>
> from scan.c to nl80211.h (or other?), and to set the default values in
> nl80211_trigger_scan() ?

Probably not nl80211.h, but more like net/wireless/scan.c or something?

Keep in mind that the defaults need to be set for both nl80211 and wext.

johannes


2012-05-29 14:28:49

by Victor Goldenshtein

[permalink] [raw]
Subject: Re: [PATCH 2/2] mac80211: handle channel times in scan command

On Tue, May 29, 2012 at 10:10 AM, Johannes Berg
<[email protected]> wrote:
> I'd prefer the default values to be defined in cfg80211, not mac80211,
> so that other drivers can also benefit once they add support for these
> settings.
>

you mean, to move (and rename) the:

#define IEEE80211_CHANNEL_TIME (HZ / 33)
#define IEEE80211_PASSIVE_CHANNEL_TIME (HZ / 8)

from scan.c to nl80211.h (or other?), and to set the default values in
nl80211_trigger_scan() ?

If so, then what about "IEEE80211_PROBE_DELAY", should we move it also ?

--
Thanks,
Victor.

2012-05-29 14:30:04

by Victor Goldenshtein

[permalink] [raw]
Subject: Re: [PATCH 1/2] nl80211/cfg80211: add scan channel times to scan command

On Tue, May 29, 2012 at 10:10 AM, Johannes Berg
<[email protected]> wrote:
> I think there may have to be some feature flag for this since otherwise
> you can't know whether you're going to be implementing 11k properly or
> not.

Will add it in v2.

--
Thanks,
Victor.

2012-05-29 07:10:37

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH 1/2] nl80211/cfg80211: add scan channel times to scan command

On Thu, 2012-05-24 at 21:52 +0300, Victor Goldenshtein wrote:
> In order to give the usermode an ability to configure
> scan channel times, and as it required for the beacon
> reports in the 802.11k standard.
>
> Add to the scan command min/max channel times. Add
> min/max passive channel times, since a single scan
> can contain both passive and active channels due to
> regulatory constraints.

I think there may have to be some feature flag for this since otherwise
you can't know whether you're going to be implementing 11k properly or
not.

johannes