2013-02-13 23:16:12

by Johannes Berg

[permalink] [raw]
Subject: [PATCH 0/3] VHT regulatory

This addresses the basic requirements for checking VHT
channel regulatory -- drivers can disable if they want,
the world roaming domain includes 80 MHz (*) and we now
tell userspace what to expect.

johannes

(*) It's not entirely clear to me why world roaming excludes
UNII-2? The comment says because of DFS, but what's the
deal with that -- if there's an AP (DFS owner) we should
be able to connect anyway??


2013-02-13 23:16:12

by Johannes Berg

[permalink] [raw]
Subject: [PATCH 3/3] cfg80211: allow drivers to selectively disable 80/160 MHz

From: Johannes Berg <[email protected]>

Some drivers might support 80 or 160 MHz only on some
channels for whatever reason, so allow them to disable
these channel widths. Also maintain the new flags when
regulatory bandwidth limitations would disable these
wide channels.

Reviewed-by: Luis R. Rodriguez <[email protected]>
Signed-off-by: Johannes Berg <[email protected]>
---
include/net/cfg80211.h | 12 ++++++++++++
net/wireless/chan.c | 7 ++++++-
net/wireless/reg.c | 8 ++++++++
3 files changed, 26 insertions(+), 1 deletion(-)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 767599c..80cf5af 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -100,6 +100,16 @@ enum ieee80211_band {
* @IEEE80211_CHAN_NO_HT40MINUS: extension channel below this channel
* is not permitted.
* @IEEE80211_CHAN_NO_OFDM: OFDM is not allowed on this channel.
+ * @IEEE80211_CHAN_NO_80MHZ: If the driver supports 80 MHz on the band,
+ * this flag indicates that an 80 MHz channel cannot use this
+ * channel as the control or any of the secondary channels.
+ * This may be due to the driver or due to regulatory bandwidth
+ * restrictions.
+ * @IEEE80211_CHAN_NO_160MHZ: If the driver supports 160 MHz on the band,
+ * this flag indicates that an 160 MHz channel cannot use this
+ * channel as the control or any of the secondary channels.
+ * This may be due to the driver or due to regulatory bandwidth
+ * restrictions.
*/
enum ieee80211_channel_flags {
IEEE80211_CHAN_DISABLED = 1<<0,
@@ -109,6 +119,8 @@ enum ieee80211_channel_flags {
IEEE80211_CHAN_NO_HT40PLUS = 1<<4,
IEEE80211_CHAN_NO_HT40MINUS = 1<<5,
IEEE80211_CHAN_NO_OFDM = 1<<6,
+ IEEE80211_CHAN_NO_80MHZ = 1<<7,
+ IEEE80211_CHAN_NO_160MHZ = 1<<8,
};

#define IEEE80211_CHAN_NO_HT40 \
diff --git a/net/wireless/chan.c b/net/wireless/chan.c
index 9053345..c770694 100644
--- a/net/wireless/chan.c
+++ b/net/wireless/chan.c
@@ -379,6 +379,7 @@ bool cfg80211_chandef_usable(struct wiphy *wiphy,
case NL80211_CHAN_WIDTH_80:
if (!vht_cap->vht_supported)
return false;
+ prohibited_flags |= IEEE80211_CHAN_NO_80MHZ;
width = 80;
break;
case NL80211_CHAN_WIDTH_160:
@@ -386,6 +387,7 @@ bool cfg80211_chandef_usable(struct wiphy *wiphy,
return false;
if (!(vht_cap->cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ))
return false;
+ prohibited_flags |= IEEE80211_CHAN_NO_160MHZ;
width = 160;
break;
default:
@@ -398,7 +400,10 @@ bool cfg80211_chandef_usable(struct wiphy *wiphy,
* allowed by the driver, or only certain combinations?
* For 40 MHz the driver can set the NO_HT40 flags, but for
* 80/160 MHz and in particular 80+80 MHz this isn't really
- * feasible -- should we ask the driver here?
+ * feasible and we only have NO_80MHZ/NO_160MHZ so far but
+ * no way to cover 80+80 MHz or more complex restrictions.
+ * Note that the restrictions also need to be advertised to
+ * userspace, for example for P2P channel selection.
*/

if (width > 20)
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 343b390..b6d01b3 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -889,6 +889,10 @@ static void handle_channel(struct wiphy *wiphy,

if (freq_range->max_bandwidth_khz < MHZ_TO_KHZ(40))
bw_flags = IEEE80211_CHAN_NO_HT40;
+ if (freq_range->max_bandwidth_khz < MHZ_TO_KHZ(80))
+ bw_flags |= IEEE80211_CHAN_NO_80MHZ;
+ if (freq_range->max_bandwidth_khz < MHZ_TO_KHZ(160))
+ bw_flags |= IEEE80211_CHAN_NO_160MHZ;

if (lr->initiator == NL80211_REGDOM_SET_BY_DRIVER &&
request_wiphy && request_wiphy == wiphy &&
@@ -1287,6 +1291,10 @@ static void handle_channel_custom(struct wiphy *wiphy,

if (freq_range->max_bandwidth_khz < MHZ_TO_KHZ(40))
bw_flags = IEEE80211_CHAN_NO_HT40;
+ if (freq_range->max_bandwidth_khz < MHZ_TO_KHZ(80))
+ bw_flags |= IEEE80211_CHAN_NO_80MHZ;
+ if (freq_range->max_bandwidth_khz < MHZ_TO_KHZ(160))
+ bw_flags |= IEEE80211_CHAN_NO_160MHZ;

chan->flags |= map_regdom_flags(reg_rule->flags) | bw_flags;
chan->max_antenna_gain = (int) MBI_TO_DBI(power_rule->max_antenna_gain);
--
1.8.0


2013-02-13 23:16:12

by Johannes Berg

[permalink] [raw]
Subject: [PATCH 2/3] cfg80211: check (VHT) bandwidth against regulatory

From: Johannes Berg <[email protected]>

Now that we can access the regulatory database without
holding locks, check the desired bandwidth against it
when a channel definition is checked. This addresses
the missing VHT bandwidth check, HT is already handled
by setting flags when the regdomain changes.

To do this modify freq_reg_info() to be callable with
RCU protection and use that, acquiring the mutex isn't
possible for this function.

Signed-off-by: Johannes Berg <[email protected]>
---
net/wireless/chan.c | 12 +++++++++++-
net/wireless/reg.c | 39 +++++++++++++++++++++++++++++++--------
net/wireless/reg.h | 3 +++
3 files changed, 45 insertions(+), 9 deletions(-)

diff --git a/net/wireless/chan.c b/net/wireless/chan.c
index 810c23c..9053345 100644
--- a/net/wireless/chan.c
+++ b/net/wireless/chan.c
@@ -10,6 +10,7 @@
#include <net/cfg80211.h>
#include "core.h"
#include "rdev-ops.h"
+#include "reg.h"

void cfg80211_chandef_create(struct cfg80211_chan_def *chandef,
struct ieee80211_channel *chan,
@@ -327,6 +328,9 @@ static bool cfg80211_secondary_chans_ok(struct wiphy *wiphy,
/* check for the other flags */
if (c->flags & prohibited_flags & ~IEEE80211_CHAN_RADAR)
return false;
+ if (!reg_check_bandwidth(wiphy, MHZ_TO_KHZ(freq),
+ MHZ_TO_KHZ(bandwidth)))
+ return false;
}

return true;
@@ -389,7 +393,13 @@ bool cfg80211_chandef_usable(struct wiphy *wiphy,
return false;
}

- /* TODO: missing regulatory check on 80/160 bandwidth */
+ /*
+ * TODO: What if there are only certain 80/160/80+80 MHz channels
+ * allowed by the driver, or only certain combinations?
+ * For 40 MHz the driver can set the NO_HT40 flags, but for
+ * 80/160 MHz and in particular 80+80 MHz this isn't really
+ * feasible -- should we ask the driver here?
+ */

if (width > 20)
prohibited_flags |= IEEE80211_CHAN_NO_OFDM;
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index bf35e1f..343b390 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -121,14 +121,14 @@ static inline void assert_reg_lock(void)

static const struct ieee80211_regdomain *get_cfg80211_regdom(void)
{
- return rcu_dereference_protected(cfg80211_regdomain,
- lockdep_is_held(&reg_mutex));
+ return rcu_dereference_check(cfg80211_regdomain,
+ lockdep_is_held(&reg_mutex));
}

static const struct ieee80211_regdomain *get_wiphy_regdom(struct wiphy *wiphy)
{
- return rcu_dereference_protected(wiphy->regd,
- lockdep_is_held(&reg_mutex));
+ return rcu_dereference_check(wiphy->regd,
+ lockdep_is_held(&reg_mutex));
}

static void rcu_free_regdom(const struct ieee80211_regdomain *r)
@@ -751,7 +751,7 @@ freq_reg_info_regd(struct wiphy *wiphy, u32 center_freq,
const struct ieee80211_reg_rule *freq_reg_info(struct wiphy *wiphy,
u32 center_freq)
{
- const struct ieee80211_regdomain *regd;
+ const struct ieee80211_regdomain *regd = NULL;
struct regulatory_request *lr = get_last_request();

/*
@@ -759,16 +759,39 @@ const struct ieee80211_reg_rule *freq_reg_info(struct wiphy *wiphy,
* IE has been processed or a user wants to help complaince further
*/
if (lr->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE &&
- lr->initiator != NL80211_REGDOM_SET_BY_USER &&
- wiphy->regd)
+ lr->initiator != NL80211_REGDOM_SET_BY_USER)
regd = get_wiphy_regdom(wiphy);
- else
+
+ if (!regd)
regd = get_cfg80211_regdom();

return freq_reg_info_regd(wiphy, center_freq, regd);
}
EXPORT_SYMBOL(freq_reg_info);

+bool reg_check_bandwidth(struct wiphy *wiphy,
+ u32 center_freq_khz, u32 bw_khz)
+{
+ const struct ieee80211_reg_rule *reg_rule;
+ bool result = false;
+
+ /*
+ * This interpretation is a bit of a strange quirk in the regulatory
+ * rules definitions that we have today: each 20 MHz channel must fit
+ * entirely into a single regulatory range, but if this range forbids
+ * using more than 20 MHz then it forbids even using a small part of
+ * this for the wider channel.
+ */
+
+ rcu_read_lock();
+ reg_rule = freq_reg_info(wiphy, center_freq_khz);
+ if (!IS_ERR(reg_rule))
+ result = reg_rule->freq_range.max_bandwidth_khz >= bw_khz;
+ rcu_read_unlock();
+
+ return result;
+}
+
#ifdef CONFIG_CFG80211_REG_DEBUG
static const char *reg_initiator_name(enum nl80211_reg_initiator initiator)
{
diff --git a/net/wireless/reg.h b/net/wireless/reg.h
index af2d5f8..d6740ab 100644
--- a/net/wireless/reg.h
+++ b/net/wireless/reg.h
@@ -35,6 +35,9 @@ int set_regdom(const struct ieee80211_regdomain *rd);

bool reg_last_request_cell_base(void);

+bool reg_check_bandwidth(struct wiphy *wiphy,
+ u32 center_freq_khz, u32 bw_khz);
+
/**
* regulatory_hint_found_beacon - hints a beacon was found on a channel
* @wiphy: the wireless device where the beacon was found on
--
1.8.0


2013-02-13 23:16:12

by Johannes Berg

[permalink] [raw]
Subject: [PATCH 1/3] regulatory: allow VHT channels in world roaming

From: Johannes Berg <[email protected]>

For VHT, the wider bandwidths (up to 160 MHz) need
to be allowed. Since world roaming only covers the
case of connecting to an AP, it can be opened up
there, we will rely on the AP to know the local
regulations.

Signed-off-by: Johannes Berg <[email protected]>
---
net/wireless/reg.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index e97d5b0..bf35e1f 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -184,14 +184,14 @@ static const struct ieee80211_regdomain world_regdom = {
NL80211_RRF_NO_IBSS |
NL80211_RRF_NO_OFDM),
/* IEEE 802.11a, channel 36..48 */
- REG_RULE(5180-10, 5240+10, 40, 6, 20,
+ REG_RULE(5180-10, 5240+10, 80, 6, 20,
NL80211_RRF_PASSIVE_SCAN |
NL80211_RRF_NO_IBSS),

- /* NB: 5260 MHz - 5700 MHz requies DFS */
+ /* NB: 5260 MHz - 5700 MHz requires DFS */

/* IEEE 802.11a, channel 149..165 */
- REG_RULE(5745-10, 5825+10, 40, 6, 20,
+ REG_RULE(5745-10, 5825+10, 80, 6, 20,
NL80211_RRF_PASSIVE_SCAN |
NL80211_RRF_NO_IBSS),

--
1.8.0


2013-02-13 23:46:04

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH 2/3] cfg80211: check (VHT) bandwidth against regulatory

On Thu, 2013-02-14 at 00:16 +0100, Johannes Berg wrote:
> From: Johannes Berg <[email protected]>
>
> Now that we can access the regulatory database without
> holding locks, check the desired bandwidth against it
> when a channel definition is checked. This addresses
> the missing VHT bandwidth check, HT is already handled
> by setting flags when the regdomain changes.

Actually, this patch isn't necessary, the next one handles the no-80 and
no-160 flags just fine ... I'll drop this.

johannes


2013-02-28 23:56:24

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH 1/3] regulatory: allow VHT channels in world roaming

On Thu, 2013-02-28 at 15:33 -0800, Luis R. Rodriguez wrote:

> > For VHT, the wider bandwidths (up to 160 MHz) need
> > to be allowed. Since world roaming only covers the
> > case of connecting to an AP, it can be opened up
> > there, we will rely on the AP to know the local
> > regulations.

> This seems reasonable to me but in your patch you only allow 80, not
> 160, any reason for that?

160 doesn't fit here yet -- I think it should be enabled when/if those
DFS channels are added, I don't see a reason they're missing there.

johannes


2013-02-28 23:34:10

by Luis R. Rodriguez

[permalink] [raw]
Subject: Re: [PATCH 1/3] regulatory: allow VHT channels in world roaming

On Wed, Feb 13, 2013 at 3:16 PM, Johannes Berg
<[email protected]> wrote:
> From: Johannes Berg <[email protected]>
>
> For VHT, the wider bandwidths (up to 160 MHz) need
> to be allowed. Since world roaming only covers the
> case of connecting to an AP, it can be opened up
> there, we will rely on the AP to know the local
> regulations.
>
> Signed-off-by: Johannes Berg <[email protected]>

This seems reasonable to me but in your patch you only allow 80, not
160, any reason for that? Michael, any thoughts, this would just be
for passive scan, STA only, we'd rely on the AP existing and having
such configuration.

Luis

2013-03-04 19:52:26

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH 1/3] regulatory: allow VHT channels in world roaming

On Mon, 2013-03-04 at 11:19 -0800, Luis R. Rodriguez wrote:
> On Thu, Feb 28, 2013 at 3:56 PM, Johannes Berg
> <[email protected]> wrote:
> > On Thu, 2013-02-28 at 15:33 -0800, Luis R. Rodriguez wrote:
> >
> >> > For VHT, the wider bandwidths (up to 160 MHz) need
> >> > to be allowed. Since world roaming only covers the
> >> > case of connecting to an AP, it can be opened up
> >> > there, we will rely on the AP to know the local
> >> > regulations.
> >
> >> This seems reasonable to me but in your patch you only allow 80, not
> >> 160, any reason for that?
> >
> > 160 doesn't fit here yet -- I think it should be enabled when/if those
> > DFS channels are added, I don't see a reason they're missing there.
>
> True. OK I checked internally and enabling VHT80 is reasonable, as for
> the DFS stuff you mentioned, you are right as well, but that should be
> done through a separate patch. The only thing to consider there is
> scan time increases considerably but seems like a reasonable
> compromise. I'm surprised no one has had issues before with this.
>
> Acked-by: Luis R. Rodriguez <[email protected]>

Ok, applied the patch then. I'll send a patch for those DFS channels
momentarily, care to take of db.txt?

johannes


2013-03-04 19:20:12

by Luis R. Rodriguez

[permalink] [raw]
Subject: Re: [PATCH 1/3] regulatory: allow VHT channels in world roaming

On Thu, Feb 28, 2013 at 3:56 PM, Johannes Berg
<[email protected]> wrote:
> On Thu, 2013-02-28 at 15:33 -0800, Luis R. Rodriguez wrote:
>
>> > For VHT, the wider bandwidths (up to 160 MHz) need
>> > to be allowed. Since world roaming only covers the
>> > case of connecting to an AP, it can be opened up
>> > there, we will rely on the AP to know the local
>> > regulations.
>
>> This seems reasonable to me but in your patch you only allow 80, not
>> 160, any reason for that?
>
> 160 doesn't fit here yet -- I think it should be enabled when/if those
> DFS channels are added, I don't see a reason they're missing there.

True. OK I checked internally and enabling VHT80 is reasonable, as for
the DFS stuff you mentioned, you are right as well, but that should be
done through a separate patch. The only thing to consider there is
scan time increases considerably but seems like a reasonable
compromise. I'm surprised no one has had issues before with this.

Acked-by: Luis R. Rodriguez <[email protected]>

Luis