diff mbox

[RFC,1/5] cfg80211: regulatory rules, fix bw checking

Message ID 1389720570-2430-2-git-send-email-janusz.dziedzic@tieto.com (mailing list archive)
State Not Applicable, archived
Headers show

Commit Message

Janusz.Dziedzic@tieto.com Jan. 14, 2014, 5:29 p.m. UTC
Allow BW cross over REG_RULES if rules continous.

Signed-off-by: Janusz Dziedzic <janusz.dziedzic@tieto.com>
---
I am not sure about rule_intersect() here ...

 net/wireless/reg.c |   68 +++++++++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 59 insertions(+), 9 deletions(-)

Comments

Johannes Berg Jan. 15, 2014, 1:23 p.m. UTC | #1
On Tue, 2014-01-14 at 18:29 +0100, Janusz Dziedzic wrote:
> Allow BW cross over REG_RULES if rules continous.
> 
> Signed-off-by: Janusz Dziedzic <janusz.dziedzic@tieto.com>
> ---
> I am not sure about rule_intersect() here ...

I'm not sure about the whole thing ...

We did discuss something like this previously (and see our todo list on
the wiki), but this isn't just some arbitrary internal change, it
completely changes the interpretation of the regulatory database.

At a minimum, that means you need a big commit log discussing the impact
of the changes etc.

johannes

--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Janusz.Dziedzic@tieto.com Jan. 15, 2014, 4:05 p.m. UTC | #2
On 15 January 2014 14:23, Johannes Berg <johannes@sipsolutions.net> wrote:
> On Tue, 2014-01-14 at 18:29 +0100, Janusz Dziedzic wrote:
>> Allow BW cross over REG_RULES if rules continous.
>>
>> Signed-off-by: Janusz Dziedzic <janusz.dziedzic@tieto.com>
>> ---
>> I am not sure about rule_intersect() here ...
>
> I'm not sure about the whole thing ...
>
> We did discuss something like this previously (and see our todo list on
> the wiki), but this isn't just some arbitrary internal change, it
> completely changes the interpretation of the regulatory database.
>

We need this because of such split DFS REG_RULE for ETSI:

-       (5250 - 5330 @ 80), (N/A, 20), DFS
-       (5490 - 5710 @ 80), (N/A, 27), DFS
+       (5250 - 5330 @ 80), (N/A, 20), (60), DFS
+       (5490 - 5590 @ 80), (N/A, 27), (60), DFS
+       (5590 - 5650 @ 80), (N/A, 27), (600), DFS   // here different
CAC time but still 80MHz should be available
+       (5650 - 5710 @ 80), (N/A, 27), (60), DFS

In the future could be also usefull for 160MHz:
        (5170 - 5250 @ 160), (N/A, 20)
        (5250 - 5330 @ 160), (N/A, 20), DFS

eg. using channels 36 - 64 @ 160MHz (with current code this is not
possible, due to BW check per single rule)
I am not sure there is a card with 160MHz support on the market today,
but who knows?

We can implement CAC time as hardcoded (already send such patches some
time ago) one but seems this is close connected with regulatory
configuration and seems like good idea put this in regulatory db.

> At a minimum, that means you need a big commit log discussing the impact
> of the changes etc.
>
Because of that I send this RFC, I wasn't sure about all possible
problems with that.
I hope Luis could help here.

BR
Janusz
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Johannes Berg Jan. 15, 2014, 8:17 p.m. UTC | #3
On Wed, 2014-01-15 at 17:05 +0100, Janusz Dziedzic wrote:

> > We did discuss something like this previously (and see our todo list on
> > the wiki), but this isn't just some arbitrary internal change, it
> > completely changes the interpretation of the regulatory database.
> >
> 
> We need this because of such split DFS REG_RULE for ETSI:

In general, I totally think what you're proposing makes sense, and I
also think we should take it further like here:
http://wireless.kernel.org/en/developers/todo-list/regulatory

However I do think that should be considered carefully in terms of the
userspace impact/change.

> -       (5250 - 5330 @ 80), (N/A, 20), DFS
> -       (5490 - 5710 @ 80), (N/A, 27), DFS
> +       (5250 - 5330 @ 80), (N/A, 20), (60), DFS
> +       (5490 - 5590 @ 80), (N/A, 27), (60), DFS
> +       (5590 - 5650 @ 80), (N/A, 27), (600), DFS   // here different
> CAC time but still 80MHz should be available
> +       (5650 - 5710 @ 80), (N/A, 27), (60), DFS
> 
> In the future could be also usefull for 160MHz:
>         (5170 - 5250 @ 160), (N/A, 20)
>         (5250 - 5330 @ 160), (N/A, 20), DFS

Yes, the whole @xyz thing is a bit superfluous, I believe it should
really be @unlimited (meaning only restriction is that it fits) for most
countries.

> We can implement CAC time as hardcoded (already send such patches some
> time ago) one but seems this is close connected with regulatory
> configuration and seems like good idea put this in regulatory db.

I totally agree, this is a good idea.

johannes

--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 7d20d84..4414fa5 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -522,9 +522,55 @@  bool reg_is_valid_request(const char *alpha2)
 	return alpha2_equal(lr->alpha2, alpha2);
 }
 
+static u32 get_frequency_diff(const struct ieee80211_reg_rule *rules,
+			      unsigned int rule_no,
+			      unsigned int rule_max)
+{
+	u32 start_freq, end_freq;
+	u32 no = rule_no;
+	const struct ieee80211_reg_rule *rule = &rules[rule_no];
+	const struct ieee80211_freq_range *freq_range = &rule->freq_range;
+	const struct ieee80211_freq_range *freq_range_tmp;
+
+	/* get start_freq */
+	while (no) {
+		rule = &rules[--no];
+		freq_range_tmp = &rule->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 */
+	rule = &rules[rule_no];
+	freq_range = &rule->freq_range;
+	no = rule_no;
+
+	while (no < rule_max - 1) {
+		rule = &rules[++no];
+		freq_range_tmp = &rule->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)
+static bool is_valid_reg_rule(const struct ieee80211_reg_rule *rules,
+			      unsigned int rule_no,
+			      unsigned int rule_max)
 {
+	const struct ieee80211_reg_rule *rule = &rules[rule_no];
 	const struct ieee80211_freq_range *freq_range = &rule->freq_range;
 	u32 freq_diff;
 
@@ -534,10 +580,17 @@  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;
 
+	if (freq_range->end_freq_khz <= freq_range->start_freq_khz)
+		return false;
+
+	/* First do quick check */
 	freq_diff = freq_range->end_freq_khz - freq_range->start_freq_khz;
+	if (freq_range->max_bandwidth_khz <= freq_diff)
+		return true;
 
-	if (freq_range->end_freq_khz <= freq_range->start_freq_khz ||
-	    freq_range->max_bandwidth_khz > freq_diff)
+	/* Next check adjacent rules (if continous) */
+	freq_diff = get_frequency_diff(rules, rule_no, rule_max);
+	if (freq_range->max_bandwidth_khz > freq_diff)
 		return false;
 
 	return true;
@@ -545,7 +598,6 @@  static bool is_valid_reg_rule(const struct ieee80211_reg_rule *rule)
 
 static bool is_valid_rd(const struct ieee80211_regdomain *rd)
 {
-	const struct ieee80211_reg_rule *reg_rule = NULL;
 	unsigned int i;
 
 	if (!rd->n_reg_rules)
@@ -554,11 +606,9 @@  static bool is_valid_rd(const struct ieee80211_regdomain *rd)
 	if (WARN_ON(rd->n_reg_rules > NL80211_MAX_SUPP_REG_RULES))
 		return false;
 
-	for (i = 0; i < rd->n_reg_rules; i++) {
-		reg_rule = &rd->reg_rules[i];
-		if (!is_valid_reg_rule(reg_rule))
+	for (i = 0; i < rd->n_reg_rules; i++)
+		if (!is_valid_reg_rule(rd->reg_rules, i, rd->n_reg_rules))
 			return false;
-	}
 
 	return true;
 }
@@ -666,7 +716,7 @@  static int reg_rules_intersect(const struct ieee80211_reg_rule *rule1,
 
 	intersected_rule->flags = rule1->flags | rule2->flags;
 
-	if (!is_valid_reg_rule(intersected_rule))
+	if (!is_valid_reg_rule(intersected_rule, 0, 1))
 		return -EINVAL;
 
 	return 0;