2015-11-23 18:27:54

by Michal Sojka

[permalink] [raw]
Subject: [PATCH v2 0/8] Regulatory and ath9k support for ITS-G5 band (5.9 GHz)

This patch series is another attempt to mainline support for ITS-G5
band (5.9 GHz) designated for Intelligent Transportation Systems.

Based on the discussion with Jouni [1], this version adds the
following restrictions for using the band:

1. Custom reg db must be provided by the user.
2. CONFIG_CFG80211_REG_ITSG5_BAND must be enabled.
3. The band is restricted to OCB mode. I.e. beaconing and scanning is
disabled.

Patches 1-3 do some refactoring and cleanup. They are independent of
the rest of the series. Patches 4-7 add regulatory support (mainly the
points mentioned above) and finally patch 8 adds support for ITS-G5 to
the ath9k driver.

[1]: http://www.mail-archive.com/[email protected]/msg13795.html


Michal Sojka (8):
cfg80211: reg: Remove unused function parameter
cfg80211: Remove unused cfg80211_can_use_iftype_chan()
cfg80211: reg: Refactor calculation of bandwidth flags
cfg80211: reg: Properly handle rules for 5 and 10 MHz channels
cfg80211: Add support for OCB-only channels
cfg80211: reg: Add NL80211_RRF_USER_REGD_NEEDED flag
cfg80211: Add Kconfig option for ITS-G5 band (5.9 GHz)
ath9k: Add support for ITS-G5 band (5.9 GHz)

drivers/net/wireless/ath/ath9k/common-init.c | 19 +++++
drivers/net/wireless/ath/ath9k/hw.h | 2 +-
drivers/net/wireless/ath/regd.c | 23 +++--
include/net/cfg80211.h | 5 ++
include/uapi/linux/nl80211.h | 6 ++
net/wireless/Kconfig | 27 ++++++
net/wireless/chan.c | 6 +-
net/wireless/core.h | 7 --
net/wireless/ibss.c | 12 ++-
net/wireless/mesh.c | 3 +-
net/wireless/nl80211.c | 12 +--
net/wireless/reg.c | 123 +++++++++++++--------------
net/wireless/scan.c | 4 +-
net/wireless/sme.c | 3 +-
net/wireless/util.c | 114 -------------------------
net/wireless/wext-sme.c | 3 +-
16 files changed, 161 insertions(+), 208 deletions(-)

--
2.5.3



2015-11-23 18:27:56

by Michal Sojka

[permalink] [raw]
Subject: [PATCH v2 5/8] cfg80211: Add support for OCB-only channels

We don't want channels designated for Intelligent Transportation Systems
to be used in other modes than OCB. We therefore introduce regulatory
and channel flags that prevent scanning (for performance reasons) and
beaconing on these channels.

Although regulatory documents do not talk about which modes to use, we
limit the mode to OCB in order to prevent accidental use of the band by
other applications.

Signed-off-by: Michal Sojka <[email protected]>
---
include/net/cfg80211.h | 2 ++
include/uapi/linux/nl80211.h | 2 ++
net/wireless/chan.c | 6 ++++--
net/wireless/ibss.c | 12 ++++++++----
net/wireless/mesh.c | 3 ++-
net/wireless/nl80211.c | 12 ++++++------
net/wireless/reg.c | 2 ++
net/wireless/scan.c | 4 ++--
net/wireless/sme.c | 3 ++-
net/wireless/wext-sme.c | 3 ++-
10 files changed, 32 insertions(+), 17 deletions(-)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 2c7bdb8..b47ac3e 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -117,6 +117,7 @@ enum ieee80211_band {
* on this channel.
* @IEEE80211_CHAN_NO_10MHZ: 10 MHz bandwidth is not permitted
* on this channel.
+ * @IEEE80211_CHAN_OCB_ONLY: only OCB mode is allowed on this channel.
*
*/
enum ieee80211_channel_flags {
@@ -133,6 +134,7 @@ enum ieee80211_channel_flags {
IEEE80211_CHAN_IR_CONCURRENT = 1<<10,
IEEE80211_CHAN_NO_20MHZ = 1<<11,
IEEE80211_CHAN_NO_10MHZ = 1<<12,
+ IEEE80211_CHAN_OCB_ONLY = 1<<13,
};

#define IEEE80211_CHAN_NO_HT40 \
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 1f0b4cf..07e6105 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -2865,6 +2865,7 @@ enum nl80211_sched_scan_match_attr {
* @NL80211_RRF_NO_HT40PLUS: channels can't be used in HT40+ operation
* @NL80211_RRF_NO_80MHZ: 80MHz operation not allowed
* @NL80211_RRF_NO_160MHZ: 160MHz operation not allowed
+ * @NL80211_RRF_OCB_ONLY: only OCB mode can be used here
*/
enum nl80211_reg_rule_flags {
NL80211_RRF_NO_OFDM = 1<<0,
@@ -2882,6 +2883,7 @@ enum nl80211_reg_rule_flags {
NL80211_RRF_NO_HT40PLUS = 1<<14,
NL80211_RRF_NO_80MHZ = 1<<15,
NL80211_RRF_NO_160MHZ = 1<<16,
+ NL80211_RRF_OCB_ONLY = 1<<17,
};

#define NL80211_RRF_PASSIVE_SCAN NL80211_RRF_NO_IR
diff --git a/net/wireless/chan.c b/net/wireless/chan.c
index 59cabc9..b1ab77a 100644
--- a/net/wireless/chan.c
+++ b/net/wireless/chan.c
@@ -804,7 +804,8 @@ static bool _cfg80211_reg_can_beacon(struct wiphy *wiphy,
{
bool res;
u32 prohibited_flags = IEEE80211_CHAN_DISABLED |
- IEEE80211_CHAN_RADAR;
+ IEEE80211_CHAN_RADAR |
+ IEEE80211_CHAN_OCB_ONLY;

trace_cfg80211_reg_can_beacon(wiphy, chandef, iftype, check_no_ir);

@@ -814,7 +815,8 @@ static bool _cfg80211_reg_can_beacon(struct wiphy *wiphy,
if (cfg80211_chandef_dfs_required(wiphy, chandef, iftype) > 0 &&
cfg80211_chandef_dfs_available(wiphy, chandef)) {
/* We can skip IEEE80211_CHAN_NO_IR if chandef dfs available */
- prohibited_flags = IEEE80211_CHAN_DISABLED;
+ prohibited_flags = IEEE80211_CHAN_DISABLED |
+ IEEE80211_CHAN_OCB_ONLY;
}

res = cfg80211_chandef_usable(wiphy, chandef, prohibited_flags);
diff --git a/net/wireless/ibss.c b/net/wireless/ibss.c
index 4c55fab..d9df7f0 100644
--- a/net/wireless/ibss.c
+++ b/net/wireless/ibss.c
@@ -258,9 +258,9 @@ int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev,

for (i = 0; i < sband->n_channels; i++) {
chan = &sband->channels[i];
- if (chan->flags & IEEE80211_CHAN_NO_IR)
- continue;
- if (chan->flags & IEEE80211_CHAN_DISABLED)
+ if (chan->flags & IEEE80211_CHAN_NO_IR ||
+ chan->flags & IEEE80211_CHAN_DISABLED ||
+ chan->flags & IEEE80211_CHAN_OCB_ONLY)
continue;
new_chan = chan;
break;
@@ -277,6 +277,9 @@ int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev,
NL80211_CHAN_NO_HT);
}

+ if (wdev->wext.ibss.chandef.chan->flags & IEEE80211_CHAN_OCB_ONLY)
+ return -EINVAL;
+
/* don't join -- SSID is not there */
if (!wdev->wext.ibss.ssid_len)
return 0;
@@ -331,7 +334,8 @@ int cfg80211_ibss_wext_siwfreq(struct net_device *dev,
if (!chan)
return -EINVAL;
if (chan->flags & IEEE80211_CHAN_NO_IR ||
- chan->flags & IEEE80211_CHAN_DISABLED)
+ chan->flags & IEEE80211_CHAN_DISABLED ||
+ chan->flags & IEEE80211_CHAN_OCB_ONLY)
return -EINVAL;
}

diff --git a/net/wireless/mesh.c b/net/wireless/mesh.c
index 092300b..99866ff 100644
--- a/net/wireless/mesh.c
+++ b/net/wireless/mesh.c
@@ -143,7 +143,8 @@ int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev,
chan = &sband->channels[i];
if (chan->flags & (IEEE80211_CHAN_NO_IR |
IEEE80211_CHAN_DISABLED |
- IEEE80211_CHAN_RADAR))
+ IEEE80211_CHAN_RADAR |
+ IEEE80211_CHAN_OCB_ONLY))
continue;
setup->chandef.chan = chan;
break;
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index c71e274..85b1df6 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -5860,8 +5860,8 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
goto out_free;
}

- /* ignore disabled channels */
- if (chan->flags & IEEE80211_CHAN_DISABLED)
+ /* ignore disabled and OCB-only channels */
+ if (chan->flags & (IEEE80211_CHAN_DISABLED | IEEE80211_CHAN_OCB_ONLY))
continue;

request->channels[i] = chan;
@@ -5880,7 +5880,7 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)

chan = &wiphy->bands[band]->channels[j];

- if (chan->flags & IEEE80211_CHAN_DISABLED)
+ if (chan->flags & (IEEE80211_CHAN_DISABLED | IEEE80211_CHAN_OCB_ONLY))
continue;

request->channels[i] = chan;
@@ -6247,8 +6247,8 @@ nl80211_parse_sched_scan(struct wiphy *wiphy, struct wireless_dev *wdev,
goto out_free;
}

- /* ignore disabled channels */
- if (chan->flags & IEEE80211_CHAN_DISABLED)
+ /* ignore disabled and OCB-only channels */
+ if (chan->flags & (IEEE80211_CHAN_DISABLED | IEEE80211_CHAN_OCB_ONLY))
continue;

request->channels[i] = chan;
@@ -6265,7 +6265,7 @@ nl80211_parse_sched_scan(struct wiphy *wiphy, struct wireless_dev *wdev,

chan = &wiphy->bands[band]->channels[j];

- if (chan->flags & IEEE80211_CHAN_DISABLED)
+ if (chan->flags & (IEEE80211_CHAN_DISABLED | IEEE80211_CHAN_OCB_ONLY))
continue;

request->channels[i] = chan;
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 35eaeeb..8b7110d 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -1048,6 +1048,8 @@ static u32 map_regdom_flags(u32 rd_flags)
channel_flags |= IEEE80211_CHAN_NO_80MHZ;
if (rd_flags & NL80211_RRF_NO_160MHZ)
channel_flags |= IEEE80211_CHAN_NO_160MHZ;
+ if (rd_flags & NL80211_RRF_OCB_ONLY)
+ channel_flags |= IEEE80211_CHAN_OCB_ONLY;
return channel_flags;
}

diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index 14d5369..67e4515 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -1236,9 +1236,9 @@ int cfg80211_wext_siwscan(struct net_device *dev,
continue;

for (j = 0; j < wiphy->bands[band]->n_channels; j++) {
- /* ignore disabled channels */
+ /* ignore disabled and OCB-only channels */
if (wiphy->bands[band]->channels[j].flags &
- IEEE80211_CHAN_DISABLED)
+ (IEEE80211_CHAN_DISABLED | IEEE80211_CHAN_OCB_ONLY))
continue;

/* If we have a wireless request structure and the
diff --git a/net/wireless/sme.c b/net/wireless/sme.c
index 8020b5b..817c879 100644
--- a/net/wireless/sme.c
+++ b/net/wireless/sme.c
@@ -103,7 +103,8 @@ static int cfg80211_conn_scan(struct wireless_dev *wdev)
continue;
for (j = 0; j < bands->n_channels; j++) {
channel = &bands->channels[j];
- if (channel->flags & IEEE80211_CHAN_DISABLED)
+ if (channel->flags & IEEE80211_CHAN_DISABLED ||
+ channel->flags & IEEE80211_CHAN_OCB_ONLY)
continue;
request->channels[i++] = channel;
}
diff --git a/net/wireless/wext-sme.c b/net/wireless/wext-sme.c
index a4e8af3..34a50c1 100644
--- a/net/wireless/wext-sme.c
+++ b/net/wireless/wext-sme.c
@@ -83,7 +83,8 @@ int cfg80211_mgd_wext_siwfreq(struct net_device *dev,
chan = ieee80211_get_channel(wdev->wiphy, freq);
if (!chan)
return -EINVAL;
- if (chan->flags & IEEE80211_CHAN_DISABLED)
+ if (chan->flags & IEEE80211_CHAN_DISABLED ||
+ chan->flags & IEEE80211_CHAN_OCB_ONLY)
return -EINVAL;
}

--
2.5.3


2015-11-23 18:27:56

by Michal Sojka

[permalink] [raw]
Subject: [PATCH v2 4/8] cfg80211: reg: Properly handle rules for 5 and 10 MHz channels

Regulatory rules are applied to channels as if the channel is at least
20 MHz wide. This is a problem when dealing with 5 and 10 MHz channels
because side channels of a regulatory rule get disabled even when they
fall into rule's frequency range.

This problem was already fixed in commit
4edd56981c8fbb349b1529a2feaf772636eb1c83, but only for custom regulatory
domains provided by drivers. Here we fix it also for all other (e.g.
user-supplied) regulatory domains.

Before that, similar commit was
reverted (e33e2241e272eddc38339692500bd1c7d8753a77) due to it allowing
running AP on channel 12 in the US regulatory domain. I have checked
that this is not possible with this change:

# iw reg set US
# iw dev wlan0 interface add wlan0_ap type __ap
# iw dev wlan0_ap set channel 12
command failed: Invalid argument (-22)

Cc: Felix Fietkau <[email protected]>
Signed-off-by: Michal Sojka <[email protected]>
---
net/wireless/reg.c | 8 ++------
1 file changed, 2 insertions(+), 6 deletions(-)

diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 0a4f548..35eaeeb 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -1201,11 +1201,6 @@ static uint32_t reg_rule_to_chan_bw_flags(const struct ieee80211_regdomain *regd
return bw_flags;
}

-/*
- * Note that right now we assume the desired channel bandwidth
- * is always 20 MHz for each individual channel (HT40 uses 20 MHz
- * per channel, the primary and the extension channel).
- */
static void handle_channel(struct wiphy *wiphy,
enum nl80211_reg_initiator initiator,
struct ieee80211_channel *chan)
@@ -1221,7 +1216,8 @@ static void handle_channel(struct wiphy *wiphy,

flags = chan->orig_flags;

- reg_rule = freq_reg_info(wiphy, MHZ_TO_KHZ(chan->center_freq));
+ reg_rule = __freq_reg_info(wiphy, MHZ_TO_KHZ(chan->center_freq),
+ MHZ_TO_KHZ(5));
if (IS_ERR(reg_rule)) {
/*
* We will disable all channels that do not match our
--
2.5.3


2015-11-27 08:44:38

by Michal Sojka

[permalink] [raw]
Subject: Re: [PATCH v2 7/8] cfg80211: Add Kconfig option for ITS-G5 band (5.9 GHz)

On Fri, Nov 27 2015, Johannes Berg wrote:
> On Thu, 2015-11-26 at 22:10 +0100, Michal Sojka wrote:
>> 
>> Because in [1] Jouni said that
>>
>>    "kernel config option + custom regdb would certainly be much
>> closer to what I'd like to see from the regulatory enforcement view
>> point"
>>
>> I also like the fact that the help text mentions the relevant
>> regulatory documents. I guess the users would appreciate that.
>>
>
> Fair enough, but I'm not really convinced that the Kconfig option is
> needed for what Jouni really required.
>
> In any case, I spoke with him yesterday and we don't think that your
> patches are going to work as is - we'll need to change the regulatory
> flags it seems. I'll comment more specifically on the patches.

OK. I'll wait for that.

-Michal

2015-11-27 08:59:13

by Michal Sojka

[permalink] [raw]
Subject: Re: [PATCH v2 5/8] cfg80211: Add support for OCB-only channels

On Fri, Nov 27 2015, Johannes Berg wrote:
> On Mon, 2015-11-23 at 19:27 +0100, Michal Sojka wrote:
>
>>  #define NL80211_RRF_PASSIVE_SCAN NL80211_RRF_NO_IR
>> diff --git a/net/wireless/chan.c b/net/wireless/chan.c
>> index 59cabc9..b1ab77a 100644
>> --- a/net/wireless/chan.c
>> +++ b/net/wireless/chan.c
>> @@ -804,7 +804,8 @@ static bool _cfg80211_reg_can_beacon(struct wiphy
>> *wiphy,
>>  {
>>   bool res;
>>   u32 prohibited_flags = IEEE80211_CHAN_DISABLED |
>> -        IEEE80211_CHAN_RADAR;
>> +        IEEE80211_CHAN_RADAR |
>> +        IEEE80211_CHAN_OCB_ONLY;
>
> So ... for the kernel, I don't *like* this approach, because it
> requires touching every single driver, and every single person who
> writes code in the future must be aware of the special handling for
> this flag.
>
> For userspace, however, this approach is simply impossible. Consider an
> older version of wpa_supplicant, that queries the channel list and
> isn't aware of the OCB_ONLY flag. This version would take the channel
> list and build a scan request with it, only to get the scan rejected
> since some channels it picked were only usable for OCB, as far as I can
> tell.
>
> I think the solution to this would be to redefine the CHAN_DISABLED
> flag to mean "channel disabled for non-ocb mode" and add a
> CHAN_OCB_ENABLED flag.
>
> Then code that knows about OCB would simply not test CHAN_DISABLED, but
> would instead test CHAN_OCB_ENABLED instead - and if that's clear OCB
> would not be permitted.
>
> However, this would have the side effect of enabling OCB *only* on OCB
> channels, which might not be a good idea, for testing purposes one
> might want to use the regular 2.4 or 5 GHz channels? If so, OCB could
> still be made to do something like
>
> ocb_usable = (flags & OCB_ENABLED) || !(flags & DISABLED);
>
> or we could even make the channel list internally maintain a
> CHAN_OCB_USABLE flag that essentially encodes the logic above.
>
> In any case, this would collapse the patch down to modifying only OCB
> code and nothing else, which is nice, and would keep existing userspace
> working since it would just see disabled channels while ignoring the
> OCB flag.

Yes, this makes perfect sense. I'll rework the patch.

-Michal

2015-11-23 18:27:54

by Michal Sojka

[permalink] [raw]
Subject: [PATCH v2 2/8] cfg80211: Remove unused cfg80211_can_use_iftype_chan()

Last caller of this function was removed in 3.17 in commit
97dc94f1d933c9df2c0b327066ea130c0e92083f.

Signed-off-by: Michal Sojka <[email protected]>
---
net/wireless/core.h | 7 ----
net/wireless/util.c | 114 ----------------------------------------------------
2 files changed, 121 deletions(-)

diff --git a/net/wireless/core.h b/net/wireless/core.h
index a618b4b..022ccad 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -416,13 +416,6 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev,
void cfg80211_process_rdev_events(struct cfg80211_registered_device *rdev);
void cfg80211_process_wdev_events(struct wireless_dev *wdev);

-int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev,
- struct wireless_dev *wdev,
- enum nl80211_iftype iftype,
- struct ieee80211_channel *chan,
- enum cfg80211_chan_mode chanmode,
- u8 radar_detect);
-
/**
* cfg80211_chandef_dfs_usable - checks if chandef is DFS usable
* @wiphy: the wiphy to validate against
diff --git a/net/wireless/util.c b/net/wireless/util.c
index baf7218..44d30cc 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -1620,120 +1620,6 @@ int cfg80211_check_combinations(struct wiphy *wiphy,
}
EXPORT_SYMBOL(cfg80211_check_combinations);

-int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev,
- struct wireless_dev *wdev,
- enum nl80211_iftype iftype,
- struct ieee80211_channel *chan,
- enum cfg80211_chan_mode chanmode,
- u8 radar_detect)
-{
- struct wireless_dev *wdev_iter;
- int num[NUM_NL80211_IFTYPES];
- struct ieee80211_channel
- *used_channels[CFG80211_MAX_NUM_DIFFERENT_CHANNELS];
- struct ieee80211_channel *ch;
- enum cfg80211_chan_mode chmode;
- int num_different_channels = 0;
- int total = 1;
- int i;
-
- ASSERT_RTNL();
-
- if (WARN_ON(hweight32(radar_detect) > 1))
- return -EINVAL;
-
- if (WARN_ON(iftype >= NUM_NL80211_IFTYPES))
- return -EINVAL;
-
- /* Always allow software iftypes */
- if (rdev->wiphy.software_iftypes & BIT(iftype)) {
- if (radar_detect)
- return -EINVAL;
- return 0;
- }
-
- memset(num, 0, sizeof(num));
- memset(used_channels, 0, sizeof(used_channels));
-
- num[iftype] = 1;
-
- /* TODO: We'll probably not need this anymore, since this
- * should only be called with CHAN_MODE_UNDEFINED. There are
- * still a couple of pending calls where other chanmodes are
- * used, but we should get rid of them.
- */
- switch (chanmode) {
- case CHAN_MODE_UNDEFINED:
- break;
- case CHAN_MODE_SHARED:
- WARN_ON(!chan);
- used_channels[0] = chan;
- num_different_channels++;
- break;
- case CHAN_MODE_EXCLUSIVE:
- num_different_channels++;
- break;
- }
-
- list_for_each_entry(wdev_iter, &rdev->wdev_list, list) {
- if (wdev_iter == wdev)
- continue;
- if (wdev_iter->iftype == NL80211_IFTYPE_P2P_DEVICE) {
- if (!wdev_iter->p2p_started)
- continue;
- } else if (wdev_iter->netdev) {
- if (!netif_running(wdev_iter->netdev))
- continue;
- } else {
- WARN_ON(1);
- }
-
- if (rdev->wiphy.software_iftypes & BIT(wdev_iter->iftype))
- continue;
-
- /*
- * We may be holding the "wdev" mutex, but now need to lock
- * wdev_iter. This is OK because once we get here wdev_iter
- * is not wdev (tested above), but we need to use the nested
- * locking for lockdep.
- */
- mutex_lock_nested(&wdev_iter->mtx, 1);
- __acquire(wdev_iter->mtx);
- cfg80211_get_chan_state(wdev_iter, &ch, &chmode, &radar_detect);
- wdev_unlock(wdev_iter);
-
- switch (chmode) {
- case CHAN_MODE_UNDEFINED:
- break;
- case CHAN_MODE_SHARED:
- for (i = 0; i < CFG80211_MAX_NUM_DIFFERENT_CHANNELS; i++)
- if (!used_channels[i] || used_channels[i] == ch)
- break;
-
- if (i == CFG80211_MAX_NUM_DIFFERENT_CHANNELS)
- return -EBUSY;
-
- if (used_channels[i] == NULL) {
- used_channels[i] = ch;
- num_different_channels++;
- }
- break;
- case CHAN_MODE_EXCLUSIVE:
- num_different_channels++;
- break;
- }
-
- num[wdev_iter->iftype]++;
- total++;
- }
-
- if (total == 1 && !radar_detect)
- return 0;
-
- return cfg80211_check_combinations(&rdev->wiphy, num_different_channels,
- radar_detect, num);
-}
-
int ieee80211_get_ratemask(struct ieee80211_supported_band *sband,
const u8 *rates, unsigned int n_rates,
u32 *mask)
--
2.5.3


2015-11-23 18:27:54

by Michal Sojka

[permalink] [raw]
Subject: [PATCH v2 1/8] cfg80211: reg: Remove unused function parameter

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

diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 2e8d6f3..43b3e57 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -1052,7 +1052,7 @@ static u32 map_regdom_flags(u32 rd_flags)
}

static const struct ieee80211_reg_rule *
-freq_reg_info_regd(struct wiphy *wiphy, u32 center_freq,
+freq_reg_info_regd(u32 center_freq,
const struct ieee80211_regdomain *regd, u32 bw)
{
int i;
@@ -1097,7 +1097,7 @@ __freq_reg_info(struct wiphy *wiphy, u32 center_freq, u32 min_bw)
u32 bw;

for (bw = MHZ_TO_KHZ(20); bw >= min_bw; bw = bw / 2) {
- reg_rule = freq_reg_info_regd(wiphy, center_freq, regd, bw);
+ reg_rule = freq_reg_info_regd(center_freq, regd, bw);
if (!IS_ERR(reg_rule))
return reg_rule;
}
@@ -1765,8 +1765,7 @@ static void handle_channel_custom(struct wiphy *wiphy,
u32 bw;

for (bw = MHZ_TO_KHZ(20); bw >= MHZ_TO_KHZ(5); bw = bw / 2) {
- reg_rule = freq_reg_info_regd(wiphy,
- MHZ_TO_KHZ(chan->center_freq),
+ reg_rule = freq_reg_info_regd(MHZ_TO_KHZ(chan->center_freq),
regd, bw);
if (!IS_ERR(reg_rule))
break;
--
2.5.3


2015-11-27 08:34:00

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH v2 5/8] cfg80211: Add support for OCB-only channels

On Mon, 2015-11-23 at 19:27 +0100, Michal Sojka wrote:

>  #define NL80211_RRF_PASSIVE_SCAN NL80211_RRF_NO_IR
> diff --git a/net/wireless/chan.c b/net/wireless/chan.c
> index 59cabc9..b1ab77a 100644
> --- a/net/wireless/chan.c
> +++ b/net/wireless/chan.c
> @@ -804,7 +804,8 @@ static bool _cfg80211_reg_can_beacon(struct wiphy
> *wiphy,
>  {
>   bool res;
>   u32 prohibited_flags = IEEE80211_CHAN_DISABLED |
> -        IEEE80211_CHAN_RADAR;
> +        IEEE80211_CHAN_RADAR |
> +        IEEE80211_CHAN_OCB_ONLY;

So ... for the kernel, I don't *like* this approach, because it
requires touching every single driver, and every single person who
writes code in the future must be aware of the special handling for
this flag.

For userspace, however, this approach is simply impossible. Consider an
older version of wpa_supplicant, that queries the channel list and
isn't aware of the OCB_ONLY flag. This version would take the channel
list and build a scan request with it, only to get the scan rejected
since some channels it picked were only usable for OCB, as far as I can
tell.

I think the solution to this would be to redefine the CHAN_DISABLED
flag to mean "channel disabled for non-ocb mode" and add a
CHAN_OCB_ENABLED flag.

Then code that knows about OCB would simply not test CHAN_DISABLED, but
would instead test CHAN_OCB_ENABLED instead - and if that's clear OCB
would not be permitted.

However, this would have the side effect of enabling OCB *only* on OCB
channels, which might not be a good idea, for testing purposes one
might want to use the regular 2.4 or 5 GHz channels? If so, OCB could
still be made to do something like

ocb_usable = (flags & OCB_ENABLED) || !(flags & DISABLED);

or we could even make the channel list internally maintain a
CHAN_OCB_USABLE flag that essentially encodes the logic above.

In any case, this would collapse the patch down to modifying only OCB
code and nothing else, which is nice, and would keep existing userspace
working since it would just see disabled channels while ignoring the
OCB flag.

johannes

2015-11-26 21:11:08

by Michal Sojka

[permalink] [raw]
Subject: Re: [PATCH v2 7/8] cfg80211: Add Kconfig option for ITS-G5 band (5.9 GHz)

On Thu, Nov 26 2015, Johannes Berg wrote:
> On Mon, 2015-11-23 at 19:27 +0100, Michal Sojka wrote:
>> This option is meant for use by drivers and other subsystems to
>> enable
>> support for the Intelligent Transportation System (ITS-G5) band. The
>> option depends on CFG80211_CERTIFICATION_ONUS as the use of this band
>> is
>> restricted. EU allows using it only for certain applications, USA
>> require certification.
>
> Hm. Why do we need this now? I see that you're checking it in ath9k, to
> enable the "ITSG5" channels, but why wouldn't you always do that, now
> that you have the extra checks with the user regdb being required and
> all?

Because in [1] Jouni said that

"kernel config option + custom regdb would certainly be much closer
to what I'd like to see from the regulatory enforcement view point"

I also like the fact that the help text mentions the relevant regulatory
documents. I guess the users would appreciate that.

-Michal

[1] http://www.mail-archive.com/[email protected]/msg13795.html

2015-11-26 17:55:33

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH v2 7/8] cfg80211: Add Kconfig option for ITS-G5 band (5.9 GHz)

On Mon, 2015-11-23 at 19:27 +0100, Michal Sojka wrote:
> This option is meant for use by drivers and other subsystems to
> enable
> support for the Intelligent Transportation System (ITS-G5) band. The
> option depends on CFG80211_CERTIFICATION_ONUS as the use of this band
> is
> restricted. EU allows using it only for certain applications, USA
> require certification.

Hm. Why do we need this now? I see that you're checking it in ath9k, to
enable the "ITSG5" channels, but why wouldn't you always do that, now
that you have the extra checks with the user regdb being required and
all?

johannes

2015-11-26 17:51:23

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH v2 4/8] cfg80211: reg: Properly handle rules for 5 and 10 MHz channels

On Mon, 2015-11-23 at 19:27 +0100, Michal Sojka wrote:
> Regulatory rules are applied to channels as if the channel is at
> least
> 20 MHz wide. This is a problem when dealing with 5 and 10 MHz
> channels
> because side channels of a regulatory rule get disabled even when
> they
> fall into rule's frequency range.
>
> This problem was already fixed in commit
> 4edd56981c8fbb349b1529a2feaf772636eb1c83, but only for custom
> regulatory
> domains provided by drivers. Here we fix it also for all other (e.g.
> user-supplied) regulatory domains.
>
> Before that, similar commit was
> reverted (e33e2241e272eddc38339692500bd1c7d8753a77) due to it
> allowing
> running AP on channel 12 in the US regulatory domain. I have checked
> that this is not possible with this change:
>
>   # iw reg set US
>   # iw dev wlan0 interface add wlan0_ap  type __ap
>   # iw dev wlan0_ap set channel 12
>   command failed: Invalid argument (-22)
>
Applied, with some fixups to the commit message :)

johannes

2015-11-23 18:27:56

by Michal Sojka

[permalink] [raw]
Subject: [PATCH v2 8/8] ath9k: Add support for ITS-G5 band (5.9 GHz)

The patch adds support for Intelligent Transportation System (ITS-G5)
band to the ath9k driver. The corresponding channels are allowed only if
CONFIG_CFG80211_REG_ITSG5_BAND is set and if the user provides custom
regulatory database. In addition, the band is limited to OCB mode.

Signed-off-by: Michal Sojka <[email protected]>
---
drivers/net/wireless/ath/ath9k/common-init.c | 19 +++++++++++++++++++
drivers/net/wireless/ath/ath9k/hw.h | 2 +-
drivers/net/wireless/ath/regd.c | 23 ++++++++++++++++++-----
3 files changed, 38 insertions(+), 6 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/common-init.c b/drivers/net/wireless/ath/ath9k/common-init.c
index a006c14..0b61c63 100644
--- a/drivers/net/wireless/ath/ath9k/common-init.c
+++ b/drivers/net/wireless/ath/ath9k/common-init.c
@@ -86,6 +86,25 @@ static const struct ieee80211_channel ath9k_5ghz_chantable[] = {
CHAN5G(5785, 35), /* Channel 157 */
CHAN5G(5805, 36), /* Channel 161 */
CHAN5G(5825, 37), /* Channel 165 */
+
+ /* ITS-G5B */
+ CHAN5G(5855, 38), /* Channel 171 */
+ CHAN5G(5860, 39), /* Channel 172 */
+ CHAN5G(5865, 40), /* Channel 173 */
+ CHAN5G(5870, 41), /* Channel 174 */
+ /* ITS-G5A */
+ CHAN5G(5875, 42), /* Channel 175 */
+ CHAN5G(5880, 43), /* Channel 176 */
+ CHAN5G(5885, 44), /* Channel 177 */
+ CHAN5G(5890, 45), /* Channel 178 */
+ CHAN5G(5895, 46), /* Channel 179 */
+ CHAN5G(5900, 47), /* Channel 180 */
+ CHAN5G(5905, 48), /* Channel 181 */
+ /* ITS-G5D */
+ CHAN5G(5910, 49), /* Channel 182 */
+ CHAN5G(5915, 50), /* Channel 183 */
+ CHAN5G(5920, 51), /* Channel 184 */
+ CHAN5G(5925, 52), /* Channel 185 */
};

/* Atheros hardware rate code addition for short premble */
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h
index 831a544..cb126ff 100644
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
@@ -73,7 +73,7 @@

#define ATH9K_RSSI_BAD -128

-#define ATH9K_NUM_CHANNELS 38
+#define ATH9K_NUM_CHANNELS 53

/* Register read/write primitives */
#define REG_WRITE(_ah, _reg, _val) \
diff --git a/drivers/net/wireless/ath/regd.c b/drivers/net/wireless/ath/regd.c
index 06ea6cc..38706ff 100644
--- a/drivers/net/wireless/ath/regd.c
+++ b/drivers/net/wireless/ath/regd.c
@@ -50,6 +50,14 @@ static int __ath_regd_init(struct ath_regulatory *reg);
#define ATH9K_5GHZ_5725_5850 REG_RULE(5725-10, 5850+10, 80, 0, 30,\
NL80211_RRF_NO_IR)

+#ifdef CONFIG_CFG80211_REG_ITSG5_BAND
+#define ATH9K_5GHZ_ITSG5 REG_RULE(5850, 5925, 10, 0, 33, \
+ NL80211_RRF_USER_REGD_NEEDED | \
+ NL80211_RRF_OCB_ONLY)
+#else
+#define ATH9K_5GHZ_ITSG5 {} /* Empty rule does not match any channel */
+#endif
+
#define ATH9K_2GHZ_ALL ATH9K_2GHZ_CH01_11, \
ATH9K_2GHZ_CH12_13, \
ATH9K_2GHZ_CH14
@@ -64,53 +72,58 @@ static int __ath_regd_init(struct ath_regulatory *reg);
/* Can be used for:
* 0x60, 0x61, 0x62 */
static const struct ieee80211_regdomain ath_world_regdom_60_61_62 = {
- .n_reg_rules = 5,
+ .n_reg_rules = 6,
.alpha2 = "99",
.reg_rules = {
ATH9K_2GHZ_ALL,
ATH9K_5GHZ_ALL,
+ ATH9K_5GHZ_ITSG5,
}
};

/* Can be used by 0x63 and 0x65 */
static const struct ieee80211_regdomain ath_world_regdom_63_65 = {
- .n_reg_rules = 4,
+ .n_reg_rules = 5,
.alpha2 = "99",
.reg_rules = {
ATH9K_2GHZ_CH01_11,
ATH9K_2GHZ_CH12_13,
ATH9K_5GHZ_NO_MIDBAND,
+ ATH9K_5GHZ_ITSG5,
}
};

/* Can be used by 0x64 only */
static const struct ieee80211_regdomain ath_world_regdom_64 = {
- .n_reg_rules = 3,
+ .n_reg_rules = 4,
.alpha2 = "99",
.reg_rules = {
ATH9K_2GHZ_CH01_11,
ATH9K_5GHZ_NO_MIDBAND,
+ ATH9K_5GHZ_ITSG5,
}
};

/* Can be used by 0x66 and 0x69 */
static const struct ieee80211_regdomain ath_world_regdom_66_69 = {
- .n_reg_rules = 3,
+ .n_reg_rules = 4,
.alpha2 = "99",
.reg_rules = {
ATH9K_2GHZ_CH01_11,
ATH9K_5GHZ_ALL,
+ ATH9K_5GHZ_ITSG5,
}
};

/* Can be used by 0x67, 0x68, 0x6A and 0x6C */
static const struct ieee80211_regdomain ath_world_regdom_67_68_6A_6C = {
- .n_reg_rules = 4,
+ .n_reg_rules = 5,
.alpha2 = "99",
.reg_rules = {
ATH9K_2GHZ_CH01_11,
ATH9K_2GHZ_CH12_13,
ATH9K_5GHZ_ALL,
+ ATH9K_5GHZ_ITSG5,
}
};

--
2.5.3


2015-11-30 10:31:03

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH v2 4/8] cfg80211: reg: Properly handle rules for 5 and 10 MHz channels

On Mon, 2015-11-30 at 11:56 +0200, Jouni Malinen wrote:
> On Mon, Nov 23, 2015 at 07:27:17PM +0100, Michal Sojka wrote:
> > Regulatory rules are applied to channels as if the channel is at
> > least
> > 20 MHz wide. This is a problem when dealing with 5 and 10 MHz
> > channels
> > because side channels of a regulatory rule get disabled even when
> > they
> > fall into rule's frequency range.
> >
> > This problem was already fixed in commit
> > 4edd56981c8fbb349b1529a2feaf772636eb1c83, but only for custom
> > regulatory
> > domains provided by drivers. Here we fix it also for all other
> > (e.g.
> > user-supplied) regulatory domains.
> >
> > Before that, similar commit was
> > reverted (e33e2241e272eddc38339692500bd1c7d8753a77) due to it
> > allowing
> > running AP on channel 12 in the US regulatory domain.
>
> I'm afraid this new patch needs to be reverted as well since it
> allows active scanning on channel 12 in the US regulatory domain.
> I.e., every full scan with this commit included results in a Probe
> Request frame being sent on channel 12..
>

I've dropped it from my tree.

johannes

2015-11-23 18:27:54

by Michal Sojka

[permalink] [raw]
Subject: [PATCH v2 7/8] cfg80211: Add Kconfig option for ITS-G5 band (5.9 GHz)

This option is meant for use by drivers and other subsystems to enable
support for the Intelligent Transportation System (ITS-G5) band. The
option depends on CFG80211_CERTIFICATION_ONUS as the use of this band is
restricted. EU allows using it only for certain applications, USA
require certification.

Signed-off-by: Michal Sojka <[email protected]>
---
net/wireless/Kconfig | 27 +++++++++++++++++++++++++++
1 file changed, 27 insertions(+)

diff --git a/net/wireless/Kconfig b/net/wireless/Kconfig
index da72ed3..faa0ab1 100644
--- a/net/wireless/Kconfig
+++ b/net/wireless/Kconfig
@@ -132,6 +132,33 @@ config CFG80211_REG_RELAX_NO_IR
support this feature by declaring the appropriate channel flags and
capabilities in their registration flow.

+config CFG80211_REG_ITSG5_BAND
+ bool "cfg80211 support for ITS-G5 band (5.9 GHz)"
+ def_bool n
+ depends on CFG80211_CERTIFICATION_ONUS
+ ---help---
+ This option enables support for Inteligent Transportation System (ITS)
+ band i.e. frequencies from 5.850 to 5.925 GHz. In Europe, the band is
+ standardized in the ETSI EN 302 663 standard. The use of this band is
+ restricted by regulatory documents mentioned below. Enable this option
+ only if you comply with them.
+
+ In Europe, the band is split into several sub-bands regulated by
+ separate documents:
+
+ - ITS-G5A (5.875 to 5.905 GHz) band is reserved for ITS road safety
+ related applications and is regulated by Commission Decision
+ 2008/671/EC.
+
+ - ITS-G5B (5.855 to 5.875 GHz) band is reserved for ITS non-safety
+ applications and is regulated by ECC Recommendation ECC/REC/(08)01.
+
+ - ITS-G5D (5.905 to 5.925 GHz) band is reserved for future ITS
+ applications and is regulated by ECC Decision ECC/DEC(02)01.
+
+ In the US, the band is regulated by FCC 03-324 and the devices using it
+ must be certified.
+
config CFG80211_DEFAULT_PS
bool "enable powersave by default"
depends on CFG80211
--
2.5.3


2015-11-26 16:47:00

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH v2 2/8] cfg80211: Remove unused cfg80211_can_use_iftype_chan()

On Mon, 2015-11-23 at 19:27 +0100, Michal Sojka wrote:
> Last caller of this function was removed in 3.17 in commit
> 97dc94f1d933c9df2c0b327066ea130c0e92083f.
>
Heh.

I've applied the first two patches for now - will review the others in
more detail later.

johannes

2015-11-26 17:48:17

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH v2 3/8] cfg80211: reg: Refactor calculation of bandwidth flags

On Mon, 2015-11-23 at 19:27 +0100, Michal Sojka wrote:
> The same piece of code appears at two places. Make a function from
> it.
>
Also applied.

johannes

2015-11-23 18:27:54

by Michal Sojka

[permalink] [raw]
Subject: [PATCH v2 3/8] cfg80211: reg: Refactor calculation of bandwidth flags

The same piece of code appears at two places. Make a function from it.

Signed-off-by: Michal Sojka <[email protected]>
---
net/wireless/reg.c | 91 ++++++++++++++++++++++--------------------------------
1 file changed, 37 insertions(+), 54 deletions(-)

diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 43b3e57..0a4f548 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -1166,6 +1166,41 @@ static void chan_reg_rule_print_dbg(const struct ieee80211_regdomain *regd,
#endif
}

+static uint32_t reg_rule_to_chan_bw_flags(const struct ieee80211_regdomain *regd,
+ const struct ieee80211_reg_rule *reg_rule,
+ const struct ieee80211_channel *chan)
+{
+ const struct ieee80211_freq_range *freq_range = NULL;
+ u32 max_bandwidth_khz, bw_flags = 0;
+
+ freq_range = &reg_rule->freq_range;
+
+ max_bandwidth_khz = freq_range->max_bandwidth_khz;
+ /* Check if auto calculation requested */
+ if (reg_rule->flags & NL80211_RRF_AUTO_BW)
+ max_bandwidth_khz = reg_get_max_bandwidth(regd, reg_rule);
+
+ /* If we get a reg_rule we can assume that at least 5Mhz fit */
+ if (!reg_does_bw_fit(freq_range, MHZ_TO_KHZ(chan->center_freq),
+ MHZ_TO_KHZ(10)))
+ bw_flags |= IEEE80211_CHAN_NO_10MHZ;
+ if (!reg_does_bw_fit(freq_range, MHZ_TO_KHZ(chan->center_freq),
+ MHZ_TO_KHZ(20)))
+ bw_flags |= IEEE80211_CHAN_NO_20MHZ;
+
+ if (max_bandwidth_khz < MHZ_TO_KHZ(10))
+ bw_flags |= IEEE80211_CHAN_NO_10MHZ;
+ if (max_bandwidth_khz < MHZ_TO_KHZ(20))
+ bw_flags |= IEEE80211_CHAN_NO_20MHZ;
+ if (max_bandwidth_khz < MHZ_TO_KHZ(40))
+ bw_flags |= IEEE80211_CHAN_NO_HT40;
+ if (max_bandwidth_khz < MHZ_TO_KHZ(80))
+ bw_flags |= IEEE80211_CHAN_NO_80MHZ;
+ if (max_bandwidth_khz < MHZ_TO_KHZ(160))
+ bw_flags |= IEEE80211_CHAN_NO_160MHZ;
+ return bw_flags;
+}
+
/*
* Note that right now we assume the desired channel bandwidth
* is always 20 MHz for each individual channel (HT40 uses 20 MHz
@@ -1178,11 +1213,9 @@ static void handle_channel(struct wiphy *wiphy,
u32 flags, bw_flags = 0;
const struct ieee80211_reg_rule *reg_rule = NULL;
const struct ieee80211_power_rule *power_rule = NULL;
- const struct ieee80211_freq_range *freq_range = NULL;
struct wiphy *request_wiphy = NULL;
struct regulatory_request *lr = get_last_request();
const struct ieee80211_regdomain *regd;
- u32 max_bandwidth_khz;

request_wiphy = wiphy_idx_to_wiphy(lr->wiphy_idx);

@@ -1223,31 +1256,7 @@ static void handle_channel(struct wiphy *wiphy,
chan_reg_rule_print_dbg(regd, chan, reg_rule);

power_rule = &reg_rule->power_rule;
- freq_range = &reg_rule->freq_range;
-
- max_bandwidth_khz = freq_range->max_bandwidth_khz;
- /* Check if auto calculation requested */
- if (reg_rule->flags & NL80211_RRF_AUTO_BW)
- max_bandwidth_khz = reg_get_max_bandwidth(regd, reg_rule);
-
- /* If we get a reg_rule we can assume that at least 5Mhz fit */
- if (!reg_does_bw_fit(freq_range, MHZ_TO_KHZ(chan->center_freq),
- MHZ_TO_KHZ(10)))
- bw_flags |= IEEE80211_CHAN_NO_10MHZ;
- if (!reg_does_bw_fit(freq_range, MHZ_TO_KHZ(chan->center_freq),
- MHZ_TO_KHZ(20)))
- bw_flags |= IEEE80211_CHAN_NO_20MHZ;
-
- if (max_bandwidth_khz < MHZ_TO_KHZ(10))
- bw_flags |= IEEE80211_CHAN_NO_10MHZ;
- if (max_bandwidth_khz < MHZ_TO_KHZ(20))
- bw_flags |= IEEE80211_CHAN_NO_20MHZ;
- if (max_bandwidth_khz < MHZ_TO_KHZ(40))
- bw_flags |= IEEE80211_CHAN_NO_HT40;
- if (max_bandwidth_khz < MHZ_TO_KHZ(80))
- bw_flags |= IEEE80211_CHAN_NO_80MHZ;
- if (max_bandwidth_khz < MHZ_TO_KHZ(160))
- bw_flags |= IEEE80211_CHAN_NO_160MHZ;
+ bw_flags = reg_rule_to_chan_bw_flags(regd, reg_rule, chan);

if (lr->initiator == NL80211_REGDOM_SET_BY_DRIVER &&
request_wiphy && request_wiphy == wiphy &&
@@ -1760,8 +1769,6 @@ static void handle_channel_custom(struct wiphy *wiphy,
u32 bw_flags = 0;
const struct ieee80211_reg_rule *reg_rule = NULL;
const struct ieee80211_power_rule *power_rule = NULL;
- const struct ieee80211_freq_range *freq_range = NULL;
- u32 max_bandwidth_khz;
u32 bw;

for (bw = MHZ_TO_KHZ(20); bw >= MHZ_TO_KHZ(5); bw = bw / 2) {
@@ -1786,31 +1793,7 @@ static void handle_channel_custom(struct wiphy *wiphy,
chan_reg_rule_print_dbg(regd, chan, reg_rule);

power_rule = &reg_rule->power_rule;
- freq_range = &reg_rule->freq_range;
-
- max_bandwidth_khz = freq_range->max_bandwidth_khz;
- /* Check if auto calculation requested */
- if (reg_rule->flags & NL80211_RRF_AUTO_BW)
- max_bandwidth_khz = reg_get_max_bandwidth(regd, reg_rule);
-
- /* If we get a reg_rule we can assume that at least 5Mhz fit */
- if (!reg_does_bw_fit(freq_range, MHZ_TO_KHZ(chan->center_freq),
- MHZ_TO_KHZ(10)))
- bw_flags |= IEEE80211_CHAN_NO_10MHZ;
- if (!reg_does_bw_fit(freq_range, MHZ_TO_KHZ(chan->center_freq),
- MHZ_TO_KHZ(20)))
- bw_flags |= IEEE80211_CHAN_NO_20MHZ;
-
- if (max_bandwidth_khz < MHZ_TO_KHZ(10))
- bw_flags |= IEEE80211_CHAN_NO_10MHZ;
- if (max_bandwidth_khz < MHZ_TO_KHZ(20))
- bw_flags |= IEEE80211_CHAN_NO_20MHZ;
- if (max_bandwidth_khz < MHZ_TO_KHZ(40))
- bw_flags |= IEEE80211_CHAN_NO_HT40;
- if (max_bandwidth_khz < MHZ_TO_KHZ(80))
- bw_flags |= IEEE80211_CHAN_NO_80MHZ;
- if (max_bandwidth_khz < MHZ_TO_KHZ(160))
- bw_flags |= IEEE80211_CHAN_NO_160MHZ;
+ bw_flags = reg_rule_to_chan_bw_flags(regd, reg_rule, chan);

chan->dfs_state_entered = jiffies;
chan->dfs_state = NL80211_DFS_USABLE;
--
2.5.3


2015-11-23 18:27:56

by Michal Sojka

[permalink] [raw]
Subject: [PATCH v2 6/8] cfg80211: reg: Add NL80211_RRF_USER_REGD_NEEDED flag

In order to prevent accidental use of Intelligent Transportation System
band (5.9 GHz), we require system integrators to provide custom
userspace regulatory database enabling the use of the band. However,
drivers that provide their own regulatory database (such as ath9k) would
not enable that band in this case, because they do not allow using other
bands than those specified in their database.

The NL80211_RRF_USER_REGD_NEEDED flag introduced in this commit allows
drivers to specify that certain band is enabled only if it is
additionally enabled in user-supplied regulatory database. If the band
is not present there, the channels are simply disabled.

Signed-off-by: Michal Sojka <[email protected]>
---
include/net/cfg80211.h | 3 +++
include/uapi/linux/nl80211.h | 4 ++++
net/wireless/reg.c | 15 +++++++++++++++
3 files changed, 22 insertions(+)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index b47ac3e..75026d3 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -118,6 +118,8 @@ enum ieee80211_band {
* @IEEE80211_CHAN_NO_10MHZ: 10 MHz bandwidth is not permitted
* on this channel.
* @IEEE80211_CHAN_OCB_ONLY: only OCB mode is allowed on this channel.
+ * @IEEE80211_CHAN_USER_REGD_NEEDED: can only be used if allowed by
+ * user-supplied regulatory domain.
*
*/
enum ieee80211_channel_flags {
@@ -135,6 +137,7 @@ enum ieee80211_channel_flags {
IEEE80211_CHAN_NO_20MHZ = 1<<11,
IEEE80211_CHAN_NO_10MHZ = 1<<12,
IEEE80211_CHAN_OCB_ONLY = 1<<13,
+ IEEE80211_CHAN_USER_REGD_NEEDED = 1<<14,
};

#define IEEE80211_CHAN_NO_HT40 \
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 07e6105..ae17589 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -2866,6 +2866,9 @@ enum nl80211_sched_scan_match_attr {
* @NL80211_RRF_NO_80MHZ: 80MHz operation not allowed
* @NL80211_RRF_NO_160MHZ: 160MHz operation not allowed
* @NL80211_RRF_OCB_ONLY: only OCB mode can be used here
+ * @NL80211_RRF_USER_REGD_NEEDED: when specified in driver's
+ * CUSTOM_REG regulatory domain, the band can only be used if it
+ * is also allowed in user-supplied regulatory domain.
*/
enum nl80211_reg_rule_flags {
NL80211_RRF_NO_OFDM = 1<<0,
@@ -2884,6 +2887,7 @@ enum nl80211_reg_rule_flags {
NL80211_RRF_NO_80MHZ = 1<<15,
NL80211_RRF_NO_160MHZ = 1<<16,
NL80211_RRF_OCB_ONLY = 1<<17,
+ NL80211_RRF_USER_REGD_NEEDED = 1<<18,
};

#define NL80211_RRF_PASSIVE_SCAN NL80211_RRF_NO_IR
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 8b7110d..9d9d826 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -1050,6 +1050,8 @@ static u32 map_regdom_flags(u32 rd_flags)
channel_flags |= IEEE80211_CHAN_NO_160MHZ;
if (rd_flags & NL80211_RRF_OCB_ONLY)
channel_flags |= IEEE80211_CHAN_OCB_ONLY;
+ if (rd_flags & NL80211_RRF_USER_REGD_NEEDED)
+ channel_flags |= IEEE80211_CHAN_USER_REGD_NEEDED;
return channel_flags;
}

@@ -1280,6 +1282,16 @@ static void handle_channel(struct wiphy *wiphy,
return;
}

+ if (lr->initiator == NL80211_REGDOM_SET_BY_USER &&
+ flags & IEEE80211_CHAN_USER_REGD_NEEDED) {
+ /* The driver allows using this frequency only if it
+ * is allowed in user-supplied regulatory domain,
+ * which is the case here. This is the only place
+ * where a disabled channel can be enabled again.
+ */
+ flags &= ~IEEE80211_CHAN_DISABLED;
+ }
+
chan->dfs_state = NL80211_DFS_USABLE;
chan->dfs_state_entered = jiffies;

@@ -1798,6 +1810,9 @@ static void handle_channel_custom(struct wiphy *wiphy,

chan->beacon_found = false;

+ if (reg_rule->flags & NL80211_RRF_USER_REGD_NEEDED)
+ chan->flags |= IEEE80211_CHAN_DISABLED;
+
if (wiphy->regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED)
chan->flags = chan->orig_flags | bw_flags |
map_regdom_flags(reg_rule->flags);
--
2.5.3


2015-11-27 09:52:51

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH v2 6/8] cfg80211: reg: Add NL80211_RRF_USER_REGD_NEEDED flag

On Fri, 2015-11-27 at 10:43 +0100, Michal Sojka wrote:

> What do you mean by "show"? nl80211_put_regdom() already sends regdom
> flags to userspace. Or do you mean introducing a new channel
> attribute and send it in nl80211_msg_put_channel()?
>

No, I meant keeping the flag - so that people can know with "iw list"
or something that they need a special regdomain to enable the channels?

johannes

2015-11-27 08:25:11

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH v2 7/8] cfg80211: Add Kconfig option for ITS-G5 band (5.9 GHz)

On Thu, 2015-11-26 at 22:10 +0100, Michal Sojka wrote:

> Because in [1] Jouni said that
>
>    "kernel config option + custom regdb would certainly be much
> closer to what I'd like to see from the regulatory enforcement view
> point"
>
> I also like the fact that the help text mentions the relevant
> regulatory documents. I guess the users would appreciate that.
>

Fair enough, but I'm not really convinced that the Kconfig option is
needed for what Jouni really required.

In any case, I spoke with him yesterday and we don't think that your
patches are going to work as is - we'll need to change the regulatory
flags it seems. I'll comment more specifically on the patches.

johannes

2015-11-27 09:44:10

by Michal Sojka

[permalink] [raw]
Subject: Re: [PATCH v2 6/8] cfg80211: reg: Add NL80211_RRF_USER_REGD_NEEDED flag

On Fri, Nov 27 2015, Johannes Berg wrote:
> On Mon, 2015-11-23 at 19:27 +0100, Michal Sojka wrote:
>> 
>> The NL80211_RRF_USER_REGD_NEEDED flag introduced in this commit
>> allows
>> drivers to specify that certain band is enabled only if it is
>> additionally enabled in user-supplied regulatory database. If the
>> band
>> is not present there, the channels are simply disabled.
>
> I can see why you'd want this flag internally (although it'll require
> rework given the comments on the previous patch) - but is there a
> reason to export it in nl80211?

I don't see any reason either. Only all regulatory rule flags
(nl80211_reg_rule_flags) happen to be "exported". Shall I add new field
(e.g. internal_flags) to struct ieee80211_reg_rule and define new enum
for it?

> Then again, perhaps it *would* be good to show this information in
> userspace?

What do you mean by "show"? nl80211_put_regdom() already sends regdom
flags to userspace. Or do you mean introducing a new channel attribute
and send it in nl80211_msg_put_channel()?

-Michal

2015-11-30 09:56:57

by Jouni Malinen

[permalink] [raw]
Subject: Re: [PATCH v2 4/8] cfg80211: reg: Properly handle rules for 5 and 10 MHz channels

On Mon, Nov 23, 2015 at 07:27:17PM +0100, Michal Sojka wrote:
> Regulatory rules are applied to channels as if the channel is at least
> 20 MHz wide. This is a problem when dealing with 5 and 10 MHz channels
> because side channels of a regulatory rule get disabled even when they
> fall into rule's frequency range.
>
> This problem was already fixed in commit
> 4edd56981c8fbb349b1529a2feaf772636eb1c83, but only for custom regulatory
> domains provided by drivers. Here we fix it also for all other (e.g.
> user-supplied) regulatory domains.
>
> Before that, similar commit was
> reverted (e33e2241e272eddc38339692500bd1c7d8753a77) due to it allowing
> running AP on channel 12 in the US regulatory domain.

I'm afraid this new patch needs to be reverted as well since it allows
active scanning on channel 12 in the US regulatory domain. I.e., every
full scan with this commit included results in a Probe Request frame
being sent on channel 12..

This 5 and 10 MHz channel case needs to be handled in a way that does
not enable 20 MHz channels that go beyond the regdb rule. Channel 12 is
2457-2477 MHz and the regdb rule for US covers 2402-2472 MHz. This used
to disable channel 12 correctly, but with this new change, that 5 MHz
range going beyond the rule is not noticed and channel 12 gets included
even with 20 MHz bandwidth.

> I have checked that this is not possible with this change:
>
> # iw reg set US
> # iw dev wlan0 interface add wlan0_ap type __ap
> # iw dev wlan0_ap set channel 12
> command failed: Invalid argument (-22)

That's not sufficient. Please take a look at a sniffer capture on what
goes out when running
iw reg set US
iw dev wlan0 scan

--
Jouni Malinen PGP id EFC895FA

2015-11-27 08:35:21

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH v2 6/8] cfg80211: reg: Add NL80211_RRF_USER_REGD_NEEDED flag

On Mon, 2015-11-23 at 19:27 +0100, Michal Sojka wrote:

> The NL80211_RRF_USER_REGD_NEEDED flag introduced in this commit
> allows
> drivers to specify that certain band is enabled only if it is
> additionally enabled in user-supplied regulatory database. If the
> band
> is not present there, the channels are simply disabled.

I can see why you'd want this flag internally (although it'll require
rework given the comments on the previous patch) - but is there a
reason to export it in nl80211? Then again, perhaps it *would* be good
to show this information in userspace?

johannes