2011-10-11 17:59:18

by Luis R. Rodriguez

[permalink] [raw]
Subject: [PATCH v2 0/7] wireless: add DFS master support

This is v2 of my DFS master support patches. The v2 addresses only 2 bits
on the wireless-regdb and leaves open what we do for the rest of the 6 bits.
The nl80211 interface remains the same but I also fixed a typo I had made in
my previous patches for the dfs region enums. I also throw in the fix for CRDA
for the odd behaviour observed on the last pad byte.

This set of 7 patches adds DFS master support to the Linux wireless subsystem.
I've reviewed future possible changes to DFS master regions and it seems that
we are not going to be having multiple DFS regions for one country, instead
we'll always have one DFS region for one country.

The changes here are spread out throughout wireless-regdb, crda the kernel and
lastly iw. The changes made allow for older verions of CRDA to work with new
wireless-regdb files with DFS region support. If you want DFS master region
support you'll need to upgrade your CRDA, your kernel and then hope someone
implements DFS master support for your respective driver.

This patch series does not have specific driver changes, although some seem to
be backing in the oven right now.

Luis R. Rodriguez (6):
wireless-regdb: Add master DFS region support
wireless-regdb: add FCC as the DFS region for US
crda: fix null string assumption for alpha2
crda: add support to send DFS master region
cfg80211: process regulatory DFS region for countries
cfg80211: pass DFS region to drivers through reg_notifier()
iw: add DFS region parsing support

db.txt | 2 +-
db2bin.py | 2 +-
dbparse.py | 25 ++++++++++++++++++++-----
3 files changed, 22 insertions(+), 7 deletions(-)

crda.c | 5 +++--
nl80211.h | 21 +++++++++++++++++++++
regdb.h | 3 ++-
reglib.h | 13 -------------
4 files changed, 26 insertions(+), 16 deletions(-)

include/linux/nl80211.h | 21 +++++++++++++++++++++
include/net/regulatory.h | 6 ++++++
net/wireless/nl80211.c | 15 +++++++++++++++
net/wireless/reg.c | 39 +++++++++++++++++++++++++++++++++++++++
net/wireless/reg.h | 1 +
5 files changed, 82 insertions(+), 0 deletions(-)

nl80211.h | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
reg.c | 31 +++++++++++++++++++++++++++++
2 files changed, 96 insertions(+), 0 deletions(-)

--
1.7.4.15.g7811d



2011-10-12 08:37:21

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH] iw: add DFS region parsing support

On Tue, 2011-10-11 at 13:25 -0700, Luis R. Rodriguez wrote:

> > Also, I prefer patches w/o nl80211.h updates.
>
> In my RFC on December the stars aligned differently and you preferred
> it together I think.

Really? I must've been confused. The reason I don't want them is that
then I can never merge something that isn't upstream yet. :)

johannes


2011-10-11 17:59:31

by Luis R. Rodriguez

[permalink] [raw]
Subject: [PATCH 1/2] wireless-regdb: Add master DFS region support

To support master DFS we add the three known DFS regions which
countries are known to support. In order to modify the regulatory
database schema in a backward compatible way we use one of
the two pad bytes which were unused. By using one of the two pad
bytes we end up keeping new regulatory databases with DFS region
support compatible with older verions of CRDA, the DFS region would
just not be sent to the kernel.

DFS master is only required for modes of operation which iniate
radiation on DFS channels, we will start supporting DFS with AP
mode of operation. Without DFS master support you cannot intiate
radiation on those channels (AP, Mesh, IBSS, P2P). Apart from support
from wireless-regd, crda and the 802.11 stack you'll also need proper
DFS support on your device driver.

A country can only map to one DFS region at a time for all frequency
regions. After this patch countries can start being mapped to their
own DFS region.

Signed-off-by: Luis R. Rodriguez <[email protected]>
---
db2bin.py | 2 +-
dbparse.py | 25 ++++++++++++++++++++-----
2 files changed, 21 insertions(+), 6 deletions(-)

diff --git a/db2bin.py b/db2bin.py
index 23d3ee2..41d3741 100755
--- a/db2bin.py
+++ b/db2bin.py
@@ -116,7 +116,7 @@ countrynames.sort()
for alpha2 in countrynames:
coll = countries[alpha2]
# struct regdb_file_reg_country
- output.write(struct.pack('>ccxxI', str(alpha2[0]), str(alpha2[1]), reg_rules_collections[coll.permissions]))
+ output.write(struct.pack('>ccxBI', str(alpha2[0]), str(alpha2[1]), coll.dfs_region, reg_rules_collections[coll.permissions]))


if len(sys.argv) > 3:
diff --git a/dbparse.py b/dbparse.py
index 2c0d738..893d64e 100755
--- a/dbparse.py
+++ b/dbparse.py
@@ -18,6 +18,12 @@ flag_definitions = {
'NO-HT40': 1<<10,
}

+dfs_regions = {
+ 'DFS-FCC': 1,
+ 'DFS-ETSI': 2,
+ 'DFS-JP': 3,
+}
+
class FreqBand(object):
def __init__(self, start, end, bw, comments=None):
self.start = start
@@ -61,6 +67,10 @@ class PowerRestriction(object):
s = self
return hash((s.max_ant_gain, s.max_eirp))

+class DFSRegionError(Exception):
+ def __init__(self, dfs_region):
+ self.dfs_region = dfs_region
+
class FlagError(Exception):
def __init__(self, flag):
self.flag = flag
@@ -90,9 +100,15 @@ class Permission(object):
return hash(self._as_tuple())

class Country(object):
- def __init__(self, permissions=None, comments=None):
+ def __init__(self, dfs_region, permissions=None, comments=None):
self._permissions = permissions or []
self.comments = comments or []
+ self.dfs_region = 0
+
+ if dfs_region:
+ if not dfs_region in dfs_regions:
+ raise DFSRegionError(dfs_region)
+ self.dfs_region = dfs_regions[dfs_region]

def add(self, perm):
assert isinstance(perm, Permission)
@@ -224,11 +240,10 @@ class DBParser(object):

def _parse_country(self, line):
try:
- cname, line = line.split(':', 1)
+ cname, cvals= line.split(':', 1)
+ dfs_region = cvals.strip()
if not cname:
self._syntax_error("'country' keyword must be followed by name")
- if line:
- self._syntax_error("extra data at end of country line")
except ValueError:
self._syntax_error("country name must be followed by colon")

@@ -239,7 +254,7 @@ class DBParser(object):
if len(cname) != 2:
self._warn("country '%s' not alpha2" % cname)
if not cname in self._countries:
- self._countries[cname] = Country(comments=self._comments)
+ self._countries[cname] = Country(dfs_region, comments=self._comments)
self._current_countries[cname] = self._countries[cname]
self._comments = []

--
1.7.4.15.g7811d


2011-10-11 20:25:28

by Luis R. Rodriguez

[permalink] [raw]
Subject: Re: [PATCH] iw: add DFS region parsing support

On Tue, Oct 11, 2011 at 12:57 PM, Johannes Berg
<[email protected]> wrote:
> On Tue, 2011-10-11 at 10:59 -0700, Luis R. Rodriguez wrote:
>
>> +     default:
>> +             printf("Uknown");
>
> typo.

Will fix.

> Also, I prefer patches w/o nl80211.h updates.

In my RFC on December the stars aligned differently and you preferred
it together I think.

Luis

2011-10-11 18:00:02

by Luis R. Rodriguez

[permalink] [raw]
Subject: [PATCH 3/4] crda: fix null string assumption for alpha2

The wireless-regdb only accounts for two bytes for
the country code but CRDA defined the alpha2 to be
as a string of length 2, and so does the nl80211 attribute
policy:

[NL80211_ATTR_REG_ALPHA2] = { .type = NLA_STRING, .len = 2 },

The meaning of a string is it'll be null terminated, so if you
do not add the null termination a country without the null termination
will not match up with the nl80211 attribute policy.

This has no impact for us unless we want to use the next available
pad byte on the wireless-regdb. This fixes CRDA by using a local copy
of the regdb's alpha2 that is properly null terminated and sending it.

The implications of this change is that new wirelesss-regdb's that
make use of the next pad byte for a country will get that country
ignored for regulatory hints sent to the kernel. At this point we
don't yet know what the next byte will be used for though so this
has no impact. The second pad byte is being used for DFS and that
is not impacted by this nor is this change required for it.

Distributions should upgrade though in case we ever do decide to use
this last precious country byte. I've tested that this indeed fixes
the bogus issue I saw when instead of using the second pad byte we
use the first pad byte. Thanks to Johannes for spotting the issue.

Signed-off-by: Johannes Berg <[email protected]>
Signed-off-by: Luis R. Rodriguez <[email protected]>
---
crda.c | 4 ++--
reglib.h | 13 -------------
2 files changed, 2 insertions(+), 15 deletions(-)

diff --git a/crda.c b/crda.c
index 6857e3f..fcb0c11 100644
--- a/crda.c
+++ b/crda.c
@@ -149,7 +149,7 @@ int main(int argc, char **argv)
struct regdb_file_header *header;
struct regdb_file_reg_country *countries;
int dblen, siglen, num_countries, i, j, r;
- char alpha2[2];
+ char alpha2[3] = {}; /* NUL-terminate */
char *env_country;
struct nl80211_state nlstate;
struct nl_cb *cb = NULL;
@@ -279,7 +279,7 @@ int main(int argc, char **argv)
sizeof(*rcoll) + num_rules * sizeof(__be32),
country->reg_collection_ptr);

- NLA_PUT_STRING(msg, NL80211_ATTR_REG_ALPHA2, (char *) country->alpha2);
+ NLA_PUT_STRING(msg, NL80211_ATTR_REG_ALPHA2, alpha2);

nl_reg_rules = nla_nest_start(msg, NL80211_ATTR_REG_RULES);
if (!nl_reg_rules) {
diff --git a/reglib.h b/reglib.h
index f3a76ef..9fe5d8b 100644
--- a/reglib.h
+++ b/reglib.h
@@ -53,21 +53,8 @@ static inline int is_alpha2(const char *alpha2)
return 0;
}

-/* Avoid stdlib */
-static inline int is_len_2(const char *alpha2)
-{
- if (alpha2[0] == '\0' || (alpha2[1] == '\0'))
- return 0;
- if (alpha2[2] == '\0')
- return 1;
- return 0;
-}
-
static inline int is_valid_regdom(const char *alpha2)
{
- if (!is_len_2(alpha2))
- return 0;
-
if (!is_alpha2(alpha2) && !is_world_regdom(alpha2))
return 0;

--
1.7.4.15.g7811d


2011-10-11 18:00:34

by Luis R. Rodriguez

[permalink] [raw]
Subject: [PATCH 5/6] cfg80211: process regulatory DFS region for countries

The wireless-regdb now has support for mapping a country to
one DFS region. CRDA sends this to us now so process it
so we can provide that hint to drivers. This will later be
used by code for processing DFS in a way that meets the
criteria for the DFS region the country belongs to.

Signed-off-by: Luis R. Rodriguez <[email protected]>
---
include/linux/nl80211.h | 21 +++++++++++++++++++++
include/net/regulatory.h | 1 +
net/wireless/nl80211.c | 15 +++++++++++++++
net/wireless/reg.c | 37 +++++++++++++++++++++++++++++++++++++
net/wireless/reg.h | 1 +
5 files changed, 75 insertions(+), 0 deletions(-)

diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index 9d797f2..2dbb799 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -1109,6 +1109,10 @@ enum nl80211_commands {
* %NL80211_CMD_TDLS_MGMT. Otherwise %NL80211_CMD_TDLS_OPER should be
* used for asking the driver to perform a TDLS operation.
*
+ * @NL80211_ATTR_DFS_REGION: region for regulatory rules which this country
+ * abides to when initiating radiation on DFS channels. A country maps
+ * to one DFS region.
+ *
* @NL80211_ATTR_MAX: highest attribute number currently defined
* @__NL80211_ATTR_AFTER_LAST: internal use
*/
@@ -1337,6 +1341,8 @@ enum nl80211_attrs {
NL80211_ATTR_TDLS_SUPPORT,
NL80211_ATTR_TDLS_EXTERNAL_SETUP,

+ NL80211_ATTR_DFS_REGION,
+
/* add attributes here, update the policy in nl80211.c */

__NL80211_ATTR_AFTER_LAST,
@@ -1843,6 +1849,21 @@ enum nl80211_reg_rule_flags {
};

/**
+ * enum nl80211_dfs_regions - regulatory DFS regions
+ *
+ * @NL80211_DFS_UNSET: Country has no DFS master region specified
+ * @NL80211_DFS_FCC_: Country follows DFS master rules from FCC
+ * @NL80211_DFS_FCC_: Country follows DFS master rules from ETSI
+ * @NL80211_DFS_JP_: Country follows DFS master rules from JP/MKK/Telec
+ */
+enum nl80211_dfs_regions {
+ NL80211_DFS_UNSET = 0,
+ NL80211_DFS_FCC = 1,
+ NL80211_DFS_ETSI = 2,
+ NL80211_DFS_JP = 3,
+};
+
+/**
* enum nl80211_survey_info - survey information
*
* These attribute types are used with %NL80211_ATTR_SURVEY_INFO
diff --git a/include/net/regulatory.h b/include/net/regulatory.h
index eb7d3c2..7399c93 100644
--- a/include/net/regulatory.h
+++ b/include/net/regulatory.h
@@ -93,6 +93,7 @@ struct ieee80211_reg_rule {
struct ieee80211_regdomain {
u32 n_reg_rules;
char alpha2[2];
+ u8 dfs_region;
struct ieee80211_reg_rule reg_rules[];
};

diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index edf655a..8d3012a 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -197,6 +197,7 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
[NL80211_ATTR_TDLS_OPERATION] = { .type = NLA_U8 },
[NL80211_ATTR_TDLS_SUPPORT] = { .type = NLA_FLAG },
[NL80211_ATTR_TDLS_EXTERNAL_SETUP] = { .type = NLA_FLAG },
+ [NL80211_ATTR_DFS_REGION] = { .type = NLA_U8 },
};

/* policy for the key attributes */
@@ -3348,6 +3349,9 @@ static int nl80211_get_reg(struct sk_buff *skb, struct genl_info *info)

NLA_PUT_STRING(msg, NL80211_ATTR_REG_ALPHA2,
cfg80211_regdomain->alpha2);
+ if (cfg80211_regdomain->dfs_region)
+ NLA_PUT_U8(msg, NL80211_ATTR_DFS_REGION,
+ cfg80211_regdomain->dfs_region);

nl_reg_rules = nla_nest_start(msg, NL80211_ATTR_REG_RULES);
if (!nl_reg_rules)
@@ -3406,6 +3410,7 @@ static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info)
char *alpha2 = NULL;
int rem_reg_rules = 0, r = 0;
u32 num_rules = 0, rule_idx = 0, size_of_regd;
+ u8 dfs_region = 0;
struct ieee80211_regdomain *rd = NULL;

if (!info->attrs[NL80211_ATTR_REG_ALPHA2])
@@ -3416,6 +3421,9 @@ static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info)

alpha2 = nla_data(info->attrs[NL80211_ATTR_REG_ALPHA2]);

+ if (info->attrs[NL80211_ATTR_DFS_REGION])
+ dfs_region = nla_get_u8(info->attrs[NL80211_ATTR_DFS_REGION]);
+
nla_for_each_nested(nl_reg_rule, info->attrs[NL80211_ATTR_REG_RULES],
rem_reg_rules) {
num_rules++;
@@ -3443,6 +3451,13 @@ static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info)
rd->alpha2[0] = alpha2[0];
rd->alpha2[1] = alpha2[1];

+ /*
+ * Disable DFS master mode if the DFS region was
+ * not supported or known on this kernel.
+ */
+ if (reg_supported_dfs_region(dfs_region))
+ rd->dfs_region = dfs_region;
+
nla_for_each_nested(nl_reg_rule, info->attrs[NL80211_ATTR_REG_RULES],
rem_reg_rules) {
nla_parse(tb, NL80211_REG_RULE_ATTR_MAX,
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 2520a1b..69141ed 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -1946,6 +1946,42 @@ static void print_rd_rules(const struct ieee80211_regdomain *rd)
}
}

+bool reg_supported_dfs_region(u8 dfs_region)
+{
+ switch (dfs_region) {
+ case NL80211_DFS_UNSET:
+ case NL80211_DFS_FCC:
+ case NL80211_DFS_ETSI:
+ case NL80211_DFS_JP:
+ return true;
+ default:
+ REG_DBG_PRINT("Ignoring uknown DFS master region: %d\n",
+ dfs_region);
+ return false;
+ }
+}
+
+static void print_dfs_region(u8 dfs_region)
+{
+ if (!dfs_region)
+ return;
+
+ switch (dfs_region) {
+ case NL80211_DFS_FCC:
+ pr_info(" DFS Master region FCC");
+ break;
+ case NL80211_DFS_ETSI:
+ pr_info(" DFS Master region ETSI");
+ break;
+ case NL80211_DFS_JP:
+ pr_info(" DFS Master region JP");
+ break;
+ default:
+ pr_info(" DFS Master region Uknown");
+ break;
+ }
+}
+
static void print_regdomain(const struct ieee80211_regdomain *rd)
{

@@ -1973,6 +2009,7 @@ static void print_regdomain(const struct ieee80211_regdomain *rd)
pr_info("Regulatory domain changed to country: %c%c\n",
rd->alpha2[0], rd->alpha2[1]);
}
+ print_dfs_region(rd->dfs_region);
print_rd_rules(rd);
}

diff --git a/net/wireless/reg.h b/net/wireless/reg.h
index 4a56799..786e414 100644
--- a/net/wireless/reg.h
+++ b/net/wireless/reg.h
@@ -5,6 +5,7 @@ extern const struct ieee80211_regdomain *cfg80211_regdomain;

bool is_world_regdom(const char *alpha2);
bool reg_is_valid_request(const char *alpha2);
+bool reg_supported_dfs_region(u8 dfs_region);

int regulatory_hint_user(const char *alpha2);

--
1.7.4.15.g7811d


2011-10-11 17:59:42

by Luis R. Rodriguez

[permalink] [raw]
Subject: [PATCH 2/2] wireless-regdb: add FCC as the DFS region for US

DFS master support in the US requires consideration for DFS
requirements as defined by the FCC rules.

Signed-off-by: Luis R. Rodriguez <[email protected]>
---
db.txt | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/db.txt b/db.txt
index f0b46d8..4b7e879 100644
--- a/db.txt
+++ b/db.txt
@@ -651,7 +651,7 @@ country TR:
country UA:
(2402 - 2482 @ 40), (N/A, 20)

-country US:
+country US: DFS-FCC
(2402 - 2472 @ 40), (3, 27)
(5170 - 5250 @ 40), (3, 17)
(5250 - 5330 @ 40), (3, 20), DFS
--
1.7.4.15.g7811d


2011-10-11 19:57:29

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH] iw: add DFS region parsing support

On Tue, 2011-10-11 at 10:59 -0700, Luis R. Rodriguez wrote:

> + default:
> + printf("Uknown");

typo. Also, I prefer patches w/o nl80211.h updates.

johannes


2011-10-12 09:13:32

by Luis R. Rodriguez

[permalink] [raw]
Subject: Re: [PATCH] iw: add DFS region parsing support

On Wed, Oct 12, 2011 at 1:37 AM, Johannes Berg
<[email protected]> wrote:
> On Tue, 2011-10-11 at 13:25 -0700, Luis R. Rodriguez wrote:
>
>> > Also, I prefer patches w/o nl80211.h updates.
>>
>> In my RFC on December the stars aligned differently and you preferred
>> it together I think.
>
> Really? I must've been confused. The reason I don't want them is that
> then I can never merge something that isn't upstream yet. :)

That's fine, I also like to split it. I'll resend the iw patches.
John, let me know if the other ones look peachy, once and if you merge
to wireless-regdb, wireless-next I'll push to CRDA too.

Luis

2011-10-11 18:02:05

by Luis R. Rodriguez

[permalink] [raw]
Subject: [PATCH] iw: add DFS region parsing support

This lets iw parse the DFS region passed on by the kernel
when one is found for the currently used regulatory domain.

Signed-off-by: Luis R. Rodriguez <[email protected]>
---
nl80211.h | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
reg.c | 31 +++++++++++++++++++++++++++++
2 files changed, 96 insertions(+), 0 deletions(-)

diff --git a/nl80211.h b/nl80211.h
index c73582f..2dbb799 100644
--- a/nl80211.h
+++ b/nl80211.h
@@ -506,6 +506,9 @@
* @NL80211_CMD_PMKSA_CANDIDATE: This is used as an event to inform userspace
* of PMKSA caching dandidates.
*
+ * @NL80211_CMD_TDLS_OPER: Perform a high-level TDLS command (e.g. link setup).
+ * @NL80211_CMD_TDLS_MGMT: Send a TDLS management frame.
+ *
* @NL80211_CMD_MAX: highest used command number
* @__NL80211_CMD_AFTER_LAST: internal use
*/
@@ -632,6 +635,9 @@ enum nl80211_commands {

NL80211_CMD_PMKSA_CANDIDATE,

+ NL80211_CMD_TDLS_OPER,
+ NL80211_CMD_TDLS_MGMT,
+
/* add new commands above here */

/* used to define NL80211_CMD_MAX below */
@@ -1089,6 +1095,24 @@ enum nl80211_commands {
* This attribute is used with %NL80211_CMD_TRIGGER_SCAN and
* %NL80211_CMD_FRAME commands.
*
+ * @NL80211_ATTR_TDLS_ACTION: Low level TDLS action code (e.g. link setup
+ * request, link setup confirm, link teardown, etc.). Values are
+ * described in the TDLS (802.11z) specification.
+ * @NL80211_ATTR_TDLS_DIALOG_TOKEN: Non-zero token for uniquely identifying a
+ * TDLS conversation between two devices.
+ * @NL80211_ATTR_TDLS_OPERATION: High level TDLS operation; see
+ * &enum nl80211_tdls_operation, represented as a u8.
+ * @NL80211_ATTR_TDLS_SUPPORT: A flag indicating the device can operate
+ * as a TDLS peer sta.
+ * @NL80211_ATTR_TDLS_EXTERNAL_SETUP: The TDLS discovery/setup and teardown
+ * procedures should be performed by sending TDLS packets via
+ * %NL80211_CMD_TDLS_MGMT. Otherwise %NL80211_CMD_TDLS_OPER should be
+ * used for asking the driver to perform a TDLS operation.
+ *
+ * @NL80211_ATTR_DFS_REGION: region for regulatory rules which this country
+ * abides to when initiating radiation on DFS channels. A country maps
+ * to one DFS region.
+ *
* @NL80211_ATTR_MAX: highest attribute number currently defined
* @__NL80211_ATTR_AFTER_LAST: internal use
*/
@@ -1311,6 +1335,14 @@ enum nl80211_attrs {

NL80211_ATTR_TX_NO_CCK_RATE,

+ NL80211_ATTR_TDLS_ACTION,
+ NL80211_ATTR_TDLS_DIALOG_TOKEN,
+ NL80211_ATTR_TDLS_OPERATION,
+ NL80211_ATTR_TDLS_SUPPORT,
+ NL80211_ATTR_TDLS_EXTERNAL_SETUP,
+
+ NL80211_ATTR_DFS_REGION,
+
/* add attributes here, update the policy in nl80211.c */

__NL80211_ATTR_AFTER_LAST,
@@ -1408,6 +1440,7 @@ enum nl80211_iftype {
* @NL80211_STA_FLAG_WME: station is WME/QoS capable
* @NL80211_STA_FLAG_MFP: station uses management frame protection
* @NL80211_STA_FLAG_AUTHENTICATED: station is authenticated
+ * @NL80211_STA_FLAG_TDLS_PEER: station is a TDLS peer
* @NL80211_STA_FLAG_MAX: highest station flag number currently defined
* @__NL80211_STA_FLAG_AFTER_LAST: internal use
*/
@@ -1418,6 +1451,7 @@ enum nl80211_sta_flags {
NL80211_STA_FLAG_WME,
NL80211_STA_FLAG_MFP,
NL80211_STA_FLAG_AUTHENTICATED,
+ NL80211_STA_FLAG_TDLS_PEER,

/* keep last */
__NL80211_STA_FLAG_AFTER_LAST,
@@ -1815,6 +1849,21 @@ enum nl80211_reg_rule_flags {
};

/**
+ * enum nl80211_dfs_regions - regulatory DFS regions
+ *
+ * @NL80211_DFS_UNSET: Country has no DFS master region specified
+ * @NL80211_DFS_FCC_: Country follows DFS master rules from FCC
+ * @NL80211_DFS_FCC_: Country follows DFS master rules from ETSI
+ * @NL80211_DFS_JP_: Country follows DFS master rules from JP/MKK/Telec
+ */
+enum nl80211_dfs_regions {
+ NL80211_DFS_UNSET = 0,
+ NL80211_DFS_FCC = 1,
+ NL80211_DFS_ETSI = 2,
+ NL80211_DFS_JP = 3,
+};
+
+/**
* enum nl80211_survey_info - survey information
*
* These attribute types are used with %NL80211_ATTR_SURVEY_INFO
@@ -2604,4 +2653,20 @@ enum nl80211_pmksa_candidate_attr {
MAX_NL80211_PMKSA_CANDIDATE = NUM_NL80211_PMKSA_CANDIDATE - 1
};

+/**
+ * enum nl80211_tdls_operation - values for %NL80211_ATTR_TDLS_OPERATION
+ * @NL80211_TDLS_DISCOVERY_REQ: Send a TDLS discovery request
+ * @NL80211_TDLS_SETUP: Setup TDLS link
+ * @NL80211_TDLS_TEARDOWN: Teardown a TDLS link which is already established
+ * @NL80211_TDLS_ENABLE_LINK: Enable TDLS link
+ * @NL80211_TDLS_DISABLE_LINK: Disable TDLS link
+ */
+enum nl80211_tdls_operation {
+ NL80211_TDLS_DISCOVERY_REQ,
+ NL80211_TDLS_SETUP,
+ NL80211_TDLS_TEARDOWN,
+ NL80211_TDLS_ENABLE_LINK,
+ NL80211_TDLS_DISABLE_LINK,
+};
+
#endif /* __LINUX_NL80211_H */
diff --git a/reg.c b/reg.c
index c4ee1c4..4fa5bec 100644
--- a/reg.c
+++ b/reg.c
@@ -96,6 +96,31 @@ COMMAND(reg, set, "<ISO/IEC 3166-1 alpha2>",
NL80211_CMD_REQ_SET_REG, 0, CIB_NONE, handle_reg_set,
"Notify the kernel about the current regulatory domain.");

+static void print_dfs_region(__u8 dfs_region)
+{
+ if (!dfs_region)
+ return;
+
+ printf("DFS Master region: ");
+
+ switch (dfs_region) {
+ case NL80211_DFS_FCC:
+ printf("FCC");
+ break;
+ case NL80211_DFS_ETSI:
+ printf("ETSI");
+ break;
+ case NL80211_DFS_JP:
+ printf("JP");
+ break;
+ default:
+ printf("Uknown");
+ break;
+ }
+
+ printf("\n");
+}
+
static int print_reg_handler(struct nl_msg *msg, void *arg)

{
@@ -107,6 +132,7 @@ static int print_reg_handler(struct nl_msg *msg, void *arg)
struct nlattr *tb_msg[NL80211_ATTR_MAX + 1];
struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
char *alpha2;
+ __u8 dfs_region = 0;
struct nlattr *nl_rule;
int rem_rule;
static struct nla_policy reg_rule_policy[NL80211_FREQUENCY_ATTR_MAX + 1] = {
@@ -132,7 +158,12 @@ static int print_reg_handler(struct nl_msg *msg, void *arg)
}

alpha2 = nla_data(tb_msg[NL80211_ATTR_REG_ALPHA2]);
+
+ if (tb_msg[NL80211_ATTR_DFS_REGION])
+ dfs_region = nla_get_u8(tb_msg[NL80211_ATTR_DFS_REGION]);
+
printf("country %c%c:\n", alpha2[0], alpha2[1]);
+ print_dfs_region(dfs_region);

nla_for_each_nested(nl_rule, tb_msg[NL80211_ATTR_REG_RULES], rem_rule) {
struct nlattr *tb_rule[NL80211_FREQUENCY_ATTR_MAX + 1];
--
1.7.4.15.g7811d


2011-10-11 18:00:14

by Luis R. Rodriguez

[permalink] [raw]
Subject: [PATCH 4/4] crda: add support to send DFS master region

wireless-regdb now has support for a DFS master region
for each country. We must read this from the file and
send it as an NL80211_ATTR_DFS_REGION attribute.

We add a "creqs" value for the country structure but only
use the first two bits as that is all we need right now.

Signed-off-by: Luis R. Rodriguez <[email protected]>
---
crda.c | 1 +
nl80211.h | 21 +++++++++++++++++++++
regdb.h | 3 ++-
3 files changed, 24 insertions(+), 1 deletions(-)

diff --git a/crda.c b/crda.c
index fcb0c11..1e2ff22 100644
--- a/crda.c
+++ b/crda.c
@@ -280,6 +280,7 @@ int main(int argc, char **argv)
country->reg_collection_ptr);

NLA_PUT_STRING(msg, NL80211_ATTR_REG_ALPHA2, alpha2);
+ NLA_PUT_U8(msg, NL80211_ATTR_DFS_REGION, country->creqs & 0x3);

nl_reg_rules = nla_nest_start(msg, NL80211_ATTR_REG_RULES);
if (!nl_reg_rules) {
diff --git a/nl80211.h b/nl80211.h
index 9d797f2..2dbb799 100644
--- a/nl80211.h
+++ b/nl80211.h
@@ -1109,6 +1109,10 @@ enum nl80211_commands {
* %NL80211_CMD_TDLS_MGMT. Otherwise %NL80211_CMD_TDLS_OPER should be
* used for asking the driver to perform a TDLS operation.
*
+ * @NL80211_ATTR_DFS_REGION: region for regulatory rules which this country
+ * abides to when initiating radiation on DFS channels. A country maps
+ * to one DFS region.
+ *
* @NL80211_ATTR_MAX: highest attribute number currently defined
* @__NL80211_ATTR_AFTER_LAST: internal use
*/
@@ -1337,6 +1341,8 @@ enum nl80211_attrs {
NL80211_ATTR_TDLS_SUPPORT,
NL80211_ATTR_TDLS_EXTERNAL_SETUP,

+ NL80211_ATTR_DFS_REGION,
+
/* add attributes here, update the policy in nl80211.c */

__NL80211_ATTR_AFTER_LAST,
@@ -1843,6 +1849,21 @@ enum nl80211_reg_rule_flags {
};

/**
+ * enum nl80211_dfs_regions - regulatory DFS regions
+ *
+ * @NL80211_DFS_UNSET: Country has no DFS master region specified
+ * @NL80211_DFS_FCC_: Country follows DFS master rules from FCC
+ * @NL80211_DFS_FCC_: Country follows DFS master rules from ETSI
+ * @NL80211_DFS_JP_: Country follows DFS master rules from JP/MKK/Telec
+ */
+enum nl80211_dfs_regions {
+ NL80211_DFS_UNSET = 0,
+ NL80211_DFS_FCC = 1,
+ NL80211_DFS_ETSI = 2,
+ NL80211_DFS_JP = 3,
+};
+
+/**
* enum nl80211_survey_info - survey information
*
* These attribute types are used with %NL80211_ATTR_SURVEY_INFO
diff --git a/regdb.h b/regdb.h
index 045a0e3..f040aa1 100644
--- a/regdb.h
+++ b/regdb.h
@@ -96,7 +96,8 @@ struct regdb_file_reg_rules_collection {

struct regdb_file_reg_country {
__u8 alpha2[2];
- __u8 PAD[2];
+ __u8 PAD;
+ __u8 creqs; /* first two bits define DFS region */
/* pointer (offset) into the file to a struct
* regdb_file_reg_rules_collection */
__be32 reg_collection_ptr;
--
1.7.4.15.g7811d


2011-10-11 18:01:47

by Luis R. Rodriguez

[permalink] [raw]
Subject: [PATCH 6/6] cfg80211: pass DFS region to drivers through reg_notifier()

This grants drivers access to the DFS region that a
regulatory domain belongs to.

Signed-off-by: Luis R. Rodriguez <[email protected]>
---
include/net/regulatory.h | 5 +++++
net/wireless/reg.c | 2 ++
2 files changed, 7 insertions(+), 0 deletions(-)

diff --git a/include/net/regulatory.h b/include/net/regulatory.h
index 7399c93..a5f7993 100644
--- a/include/net/regulatory.h
+++ b/include/net/regulatory.h
@@ -48,6 +48,10 @@ enum environment_cap {
* 99 - built by driver but a specific alpha2 cannot be determined
* 98 - result of an intersection between two regulatory domains
* 97 - regulatory domain has not yet been configured
+ * @dfs_region: If CRDA responded with a regulatory domain that requires
+ * DFS master operation on a known DFS region (NL80211_DFS_*),
+ * dfs_region represents that region. Drivers can use this and the
+ * @alpha2 to adjust their device's DFS parameters as required.
* @intersect: indicates whether the wireless core should intersect
* the requested regulatory domain with the presently set regulatory
* domain.
@@ -67,6 +71,7 @@ struct regulatory_request {
int wiphy_idx;
enum nl80211_reg_initiator initiator;
char alpha2[2];
+ u8 dfs_region;
bool intersect;
bool processed;
enum environment_cap country_ie_env;
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 69141ed..b66444d 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -1121,6 +1121,8 @@ static void wiphy_update_regulatory(struct wiphy *wiphy,
if (ignore_reg_update(wiphy, initiator))
return;

+ last_request->dfs_region = cfg80211_regdomain->dfs_region;
+
for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
if (wiphy->bands[band])
handle_band(wiphy, band, initiator);
--
1.7.4.15.g7811d