Introduce new way to calculate maximum available bandwidth.
Before we get this form regulatory rule.
Currently we calculate this from contiguous rules and base
on such calculation we set correct channel BW flags (40, 80, 160MHz).
In case someone will need to use bandwidth defined in regulatory
database only I also introduce new regulatory rule flag STRICT-BW.
In such case maximum bandwidth from regulatory database will be
used.
Tested with hwsim.
Janusz Dziedzic (5):
cfg80211: don't check regulatory bandwidth
cfg80211: add helper reg_get_regdomain() function
cfg80211: fix maximum bandwidth calculation
cfg80211: introduce strict bandwidth regulatory flag
cfg80211: parse STRICT-BW flag for insternal regdb option
include/uapi/linux/nl80211.h | 2 +
net/wireless/genregdb.awk | 2 +
net/wireless/reg.c | 107 ++++++++++++++++++++++++++++++++++++------
3 files changed, 96 insertions(+), 15 deletions(-)
--
1.7.9.5
Calculate maximum bandwidth base on all contiguous
regulatory rules, instead of single rule.
Base on this calculation mark channel BW flags
correctly.
Signed-off-by: Janusz Dziedzic <[email protected]>
---
net/wireless/reg.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 57 insertions(+), 3 deletions(-)
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 71d360c..8165303 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -541,6 +541,55 @@ static const struct ieee80211_regdomain *reg_get_regdomain(struct wiphy *wiphy)
return regd;
}
+static unsigned int reg_get_max_bandwidth(const struct ieee80211_regdomain *rd,
+ const struct ieee80211_reg_rule *rule)
+{
+ const struct ieee80211_freq_range *freq_range = &rule->freq_range;
+ const struct ieee80211_freq_range *freq_range_tmp;
+ const struct ieee80211_reg_rule *tmp;
+ u32 start_freq, end_freq, idx, no;
+
+ for (idx = 0; idx < rd->n_reg_rules; idx++)
+ if (rule == &rd->reg_rules[idx])
+ break;
+
+ if (idx == rd->n_reg_rules)
+ return 0;
+
+ /* get start_freq */
+ no = idx;
+
+ while (no) {
+ tmp = &rd->reg_rules[--no];
+ freq_range_tmp = &tmp->freq_range;
+
+ if (freq_range_tmp->end_freq_khz < freq_range->start_freq_khz)
+ break;
+
+ freq_range = freq_range_tmp;
+ };
+
+ start_freq = freq_range->start_freq_khz;
+
+ /* get end_freq */
+ freq_range = &rule->freq_range;
+ no = idx;
+
+ while (no < rd->n_reg_rules - 1) {
+ tmp = &rd->reg_rules[++no];
+ freq_range_tmp = &tmp->freq_range;
+
+ if (freq_range_tmp->start_freq_khz > freq_range->end_freq_khz)
+ break;
+
+ freq_range = freq_range_tmp;
+ }
+
+ end_freq = freq_range->end_freq_khz;
+
+ return end_freq - start_freq;
+}
+
/* Sanity check on a regulatory rule */
static bool is_valid_reg_rule(const struct ieee80211_reg_rule *rule)
{
@@ -908,6 +957,8 @@ static void handle_channel(struct wiphy *wiphy,
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);
@@ -949,11 +1000,14 @@ static void handle_channel(struct wiphy *wiphy,
power_rule = ®_rule->power_rule;
freq_range = ®_rule->freq_range;
- if (freq_range->max_bandwidth_khz < MHZ_TO_KHZ(40))
+ regd = reg_get_regdomain(wiphy);
+ max_bandwidth_khz = reg_get_max_bandwidth(regd, reg_rule);
+
+ if (max_bandwidth_khz < MHZ_TO_KHZ(40))
bw_flags = IEEE80211_CHAN_NO_HT40;
- if (freq_range->max_bandwidth_khz < MHZ_TO_KHZ(80))
+ if (max_bandwidth_khz < MHZ_TO_KHZ(80))
bw_flags |= IEEE80211_CHAN_NO_80MHZ;
- if (freq_range->max_bandwidth_khz < MHZ_TO_KHZ(160))
+ if (max_bandwidth_khz < MHZ_TO_KHZ(160))
bw_flags |= IEEE80211_CHAN_NO_160MHZ;
if (lr->initiator == NL80211_REGDOM_SET_BY_DRIVER &&
--
1.7.9.5
On Fri, 2014-01-17 at 09:32 +0100, Janusz Dziedzic wrote:
> Introduce NL80211_RRF_STRICT_BW regulatory rule flag.
> This mean we will check only banwidth defined in
> regulatory database and not check contiguous rules.
If you meant for this to alleviate my concerns about crda/db.txt
compatibility, you didn't do it right. This has no value whatsoever
since it still breaks things.
johannes
Add support for parsing STRICT-BW flag when internal
regulatory database is used.
Signed-off-by: Janusz Dziedzic <[email protected]>
---
net/wireless/genregdb.awk | 2 ++
1 file changed, 2 insertions(+)
diff --git a/net/wireless/genregdb.awk b/net/wireless/genregdb.awk
index 9a8217d..f7aeca9 100644
--- a/net/wireless/genregdb.awk
+++ b/net/wireless/genregdb.awk
@@ -105,6 +105,8 @@ function parse_reg_rule()
flags = flags "\n\t\t\tNL80211_RRF_NO_IR | "
} else if (flagarray[arg] == "NO-IR") {
flags = flags "\n\t\t\tNL80211_RRF_NO_IR | "
+ } else if (flagarray[arg] == "STRICT-BW") {
+ flags = flags "\n\t\t\tNL80211_RRF_STRICT_BW | "
}
}
--
1.7.9.5
Introduce NL80211_RRF_STRICT_BW regulatory rule flag.
This mean we will check only banwidth defined in
regulatory database and not check contiguous rules.
Signed-off-by: Janusz Dziedzic <[email protected]>
---
include/uapi/linux/nl80211.h | 2 ++
net/wireless/reg.c | 18 ++++++++++++++++++
2 files changed, 20 insertions(+)
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 91054fd..6a4fa90 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -2475,6 +2475,7 @@ enum nl80211_sched_scan_match_attr {
* @NL80211_RRF_PTP_ONLY: this is only for Point To Point links
* @NL80211_RRF_PTMP_ONLY: this is only for Point To Multi Point links
* @NL80211_RRF_NO_IR: no mechanisms that initiate radiation are allowed,
+ * @NL80211_RRF_STRICT_BW: strict BW setting
* this includes probe requests or modes of operation that require
* beaconing.
*/
@@ -2488,6 +2489,7 @@ enum nl80211_reg_rule_flags {
NL80211_RRF_PTMP_ONLY = 1<<6,
NL80211_RRF_NO_IR = 1<<7,
__NL80211_RRF_NO_IBSS = 1<<8,
+ NL80211_RRF_STRICT_BW = 1<<9,
};
#define NL80211_RRF_PASSIVE_SCAN NL80211_RRF_NO_IR
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 8165303..8c337f2 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -549,6 +549,11 @@ static unsigned int reg_get_max_bandwidth(const struct ieee80211_regdomain *rd,
const struct ieee80211_reg_rule *tmp;
u32 start_freq, end_freq, idx, no;
+ /* First check if STRICT_BW flag */
+ if (rule->flags & NL80211_RRF_STRICT_BW)
+ return freq_range->max_bandwidth_khz;
+
+ /* Next check contiguous rules */
for (idx = 0; idx < rd->n_reg_rules; idx++)
if (rule == &rd->reg_rules[idx])
break;
@@ -566,6 +571,9 @@ static unsigned int reg_get_max_bandwidth(const struct ieee80211_regdomain *rd,
if (freq_range_tmp->end_freq_khz < freq_range->start_freq_khz)
break;
+ if (tmp->flags & NL80211_RRF_STRICT_BW)
+ break;
+
freq_range = freq_range_tmp;
};
@@ -582,6 +590,9 @@ static unsigned int reg_get_max_bandwidth(const struct ieee80211_regdomain *rd,
if (freq_range_tmp->start_freq_khz > freq_range->end_freq_khz)
break;
+ if (tmp->flags & NL80211_RRF_STRICT_BW)
+ break;
+
freq_range = freq_range_tmp;
}
@@ -594,6 +605,7 @@ static unsigned int reg_get_max_bandwidth(const struct ieee80211_regdomain *rd,
static bool is_valid_reg_rule(const struct ieee80211_reg_rule *rule)
{
const struct ieee80211_freq_range *freq_range = &rule->freq_range;
+ u32 freq_diff;
if (freq_range->start_freq_khz <= 0 || freq_range->end_freq_khz <= 0)
return false;
@@ -604,6 +616,12 @@ static bool is_valid_reg_rule(const struct ieee80211_reg_rule *rule)
if (freq_range->end_freq_khz <= freq_range->start_freq_khz)
return false;
+ freq_diff = freq_range->end_freq_khz - freq_range->start_freq_khz;
+
+ if ((rule->flags & NL80211_RRF_STRICT_BW) &&
+ freq_range->max_bandwidth_khz > freq_diff)
+ return false;
+
return true;
}
--
1.7.9.5
On Fri, 2014-01-17 at 09:32 +0100, Janusz Dziedzic wrote:
> Calculate maximum bandwidth base on all contiguous
> regulatory rules, instead of single rule.
> Base on this calculation mark channel BW flags
> correctly.
I can't consider this a "fix". In absence of other information, this is
a userspace API change. It might be possible that I'll let you get away
with it if we assume that everybody mostly just uses the official db.txt
and you can show that it doesn't lead to different interpretation of the
rules, but there's no way I'll apply this patch as a "fix" with just
four lines of commit log.
johannes
On 20 January 2014 11:55, Johannes Berg <[email protected]> wrote:
> On Fri, 2014-01-17 at 09:32 +0100, Janusz Dziedzic wrote:
>> Introduce NL80211_RRF_STRICT_BW regulatory rule flag.
>> This mean we will check only banwidth defined in
>> regulatory database and not check contiguous rules.
>
> If you meant for this to alleviate my concerns about crda/db.txt
> compatibility, you didn't do it right. This has no value whatsoever
> since it still breaks things.
>
So, maybe better introduce opposite logic here. By default always
calculate BW as STRICT_BW - be backwards compatible with current
crda/db.txt implementation/calculation.
And introduce WIDE(LOOSE)_BW flag for the rules we would like
calculate maximum bandwidth using contiguous rules?
BR
Janusz
On Fri, 2014-01-17 at 09:32 +0100, Janusz Dziedzic wrote:
> Don't check regulatory bandwith base on
> single regulatory rule. There will be introduced
> new code that will calculate maximum bandwidth
> base on all contiguous rules.
I don't think you should break code like that in the middle.
johannes
Add helper function that will return regdomain.
Follow the driver's regulatory domain, if present,
unless a country IE has been processed or a user
wants to help complaince further.
Signed-off-by: Janusz Dziedzic <[email protected]>
---
net/wireless/reg.c | 31 ++++++++++++++++++++-----------
1 file changed, 20 insertions(+), 11 deletions(-)
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 89bfac1..71d360c 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -522,6 +522,25 @@ bool reg_is_valid_request(const char *alpha2)
return alpha2_equal(lr->alpha2, alpha2);
}
+static const struct ieee80211_regdomain *reg_get_regdomain(struct wiphy *wiphy)
+{
+ const struct ieee80211_regdomain *regd;
+ struct regulatory_request *lr = get_last_request();
+
+ /*
+ * Follow the driver's regulatory domain, if present, unless a country
+ * 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)
+ regd = get_wiphy_regdom(wiphy);
+ else
+ regd = get_cfg80211_regdom();
+
+ return regd;
+}
+
/* Sanity check on a regulatory rule */
static bool is_valid_reg_rule(const struct ieee80211_reg_rule *rule)
{
@@ -817,18 +836,8 @@ const struct ieee80211_reg_rule *freq_reg_info(struct wiphy *wiphy,
u32 center_freq)
{
const struct ieee80211_regdomain *regd;
- struct regulatory_request *lr = get_last_request();
- /*
- * Follow the driver's regulatory domain, if present, unless a country
- * 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)
- regd = get_wiphy_regdom(wiphy);
- else
- regd = get_cfg80211_regdom();
+ regd = reg_get_regdomain(wiphy);
return freq_reg_info_regd(wiphy, center_freq, regd);
}
--
1.7.9.5
Don't check regulatory bandwith base on
single regulatory rule. There will be introduced
new code that will calculate maximum bandwidth
base on all contiguous rules.
Signed-off-by: Janusz Dziedzic <[email protected]>
---
net/wireless/reg.c | 6 +-----
1 file changed, 1 insertion(+), 5 deletions(-)
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 7d20d84..89bfac1 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -526,7 +526,6 @@ bool reg_is_valid_request(const char *alpha2)
static bool is_valid_reg_rule(const struct ieee80211_reg_rule *rule)
{
const struct ieee80211_freq_range *freq_range = &rule->freq_range;
- u32 freq_diff;
if (freq_range->start_freq_khz <= 0 || freq_range->end_freq_khz <= 0)
return false;
@@ -534,10 +533,7 @@ static bool is_valid_reg_rule(const struct ieee80211_reg_rule *rule)
if (freq_range->start_freq_khz > freq_range->end_freq_khz)
return false;
- freq_diff = freq_range->end_freq_khz - freq_range->start_freq_khz;
-
- if (freq_range->end_freq_khz <= freq_range->start_freq_khz ||
- freq_range->max_bandwidth_khz > freq_diff)
+ if (freq_range->end_freq_khz <= freq_range->start_freq_khz)
return false;
return true;
--
1.7.9.5
On Mon, 2014-01-20 at 13:02 +0100, Janusz Dziedzic wrote:
> On 20 January 2014 11:55, Johannes Berg <[email protected]> wrote:
> > On Fri, 2014-01-17 at 09:32 +0100, Janusz Dziedzic wrote:
> >> Introduce NL80211_RRF_STRICT_BW regulatory rule flag.
> >> This mean we will check only banwidth defined in
> >> regulatory database and not check contiguous rules.
> >
> > If you meant for this to alleviate my concerns about crda/db.txt
> > compatibility, you didn't do it right. This has no value whatsoever
> > since it still breaks things.
> >
>
> So, maybe better introduce opposite logic here. By default always
> calculate BW as STRICT_BW - be backwards compatible with current
> crda/db.txt implementation/calculation.
> And introduce WIDE(LOOSE)_BW flag for the rules we would like
> calculate maximum bandwidth using contiguous rules?
Yeah I suppose that'd work. I think it doesn't even need to be a rule
flag, but rather a country flag?
johannes