2011-05-03 23:57:30

by Javier Cardona

[permalink] [raw]
Subject: Support for secure mesh in userspace and other mesh fixes

These patches add the capability of implementing the Authenticated Mesh Peering
Exchange entirely in userspace. Open mesh networks can still be created
without the need of a userspace daemon. For secured mesh networks, the daemon
takes control of the lifetime and the peer link state of mesh peers.

While working on this we encountered a few issues with the mesh stack which are
that are fixed in separate patches also included in this series.

For a working userspace authentication daemon you can look at the ampe branch here:
https://github.com/cozybit/authsae/tree/ampe

Cheers,

Javier



2011-05-03 23:57:36

by Javier Cardona

[permalink] [raw]
Subject: [PATCH 04/13] open80211s: Stop using zero for address 3 in mesh plink mgmt frames

Previous versions of 11s draft used the all zeroes address. Current
draft uses the same address as address 2.

Also, use the ANA-approved action category code for peer establishment frames.

Note: This breaks compatibility with previous mesh protocol instances.

Signed-off-by: Javier Cardona <[email protected]>
---
net/mac80211/mesh_plink.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c
index 0120e9e..2c37bee 100644
--- a/net/mac80211/mesh_plink.c
+++ b/net/mac80211/mesh_plink.c
@@ -43,7 +43,7 @@
#define dot11MeshMaxPeerLinks(s) (s->u.mesh.mshcfg.dot11MeshMaxPeerLinks)

enum plink_frame_type {
- PLINK_OPEN = 0,
+ PLINK_OPEN = 1,
PLINK_CONFIRM,
PLINK_CLOSE
};
@@ -181,7 +181,7 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
IEEE80211_STYPE_ACTION);
memcpy(mgmt->da, da, ETH_ALEN);
memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
- /* BSSID is left zeroed, wildcard value */
+ memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN);
mgmt->u.action.category = WLAN_CATEGORY_MESH_ACTION;
mgmt->u.action.u.plink_action.action_code = action;

--
1.7.1


2011-05-03 23:57:33

by Javier Cardona

[permalink] [raw]
Subject: [PATCH 02/13] mac80211: Let userspace send action frames over mesh interfaces

Signed-off-by: Javier Cardona <[email protected]>
---
net/wireless/mlme.c | 10 ++++++++++
1 files changed, 10 insertions(+), 0 deletions(-)

diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
index 16881fe..493b939 100644
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
@@ -963,6 +963,16 @@ int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev,
if (memcmp(mgmt->bssid, dev->dev_addr, ETH_ALEN))
err = -EINVAL;
break;
+ case NL80211_IFTYPE_MESH_POINT:
+ if (memcmp(mgmt->sa, mgmt->bssid, ETH_ALEN)) {
+ err = -EINVAL;
+ break;
+ }
+ /*
+ * check for mesh DA must be done by driver as
+ * cfg80211 doesn't track the stations
+ */
+ break;
default:
err = -EOPNOTSUPP;
break;
--
1.7.1


2011-05-03 23:57:39

by Javier Cardona

[permalink] [raw]
Subject: [PATCH 06/13] nl80211: allow installing keys for a meshif

From: Thomas Pedersen <[email protected]>

Signed-off-by: Thomas Pedersen <[email protected]>
Signed-off-by: Javier Cardona <[email protected]>
---
net/mac80211/cfg.c | 5 ++++-
net/wireless/nl80211.c | 1 +
2 files changed, 5 insertions(+), 1 deletions(-)

diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index dbc5bcb..852cb85 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -136,7 +136,10 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
mutex_lock(&sdata->local->sta_mtx);

if (mac_addr) {
- sta = sta_info_get_bss(sdata, mac_addr);
+ if (ieee80211_vif_is_mesh(&sdata->vif))
+ sta = sta_info_get(sdata, mac_addr);
+ else
+ sta = sta_info_get_bss(sdata, mac_addr);
if (!sta) {
ieee80211_key_free(sdata->local, key);
err = -ENOENT;
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 49f220a..176d118 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -535,6 +535,7 @@ static int nl80211_key_allowed(struct wireless_dev *wdev)
case NL80211_IFTYPE_AP:
case NL80211_IFTYPE_AP_VLAN:
case NL80211_IFTYPE_P2P_GO:
+ case NL80211_IFTYPE_MESH_POINT:
break;
case NL80211_IFTYPE_ADHOC:
if (!wdev->current_bss)
--
1.7.1


2011-05-04 17:25:20

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH 13/13] ath9k: fix beaconing for mesh interfaces

On Wed, 2011-05-04 at 10:13 -0700, Javier Cardona wrote:

> The current version of the draft defines a different beaconing mode
> specific for mesh.

Out of curiosity, what does that mode look like?

johannes


2011-05-04 16:32:52

by Javier Cardona

[permalink] [raw]
Subject: Re: [PATCH 01/13] nl80211: Introduce NL80211_MESH_SETUP_USERSPACE_AMPE

On Wed, May 4, 2011 at 5:27 AM, Johannes Berg <[email protected]> wrote:
> On Tue, 2011-05-03 at 16:57 -0700, Javier Cardona wrote:
>
>> These patches introduce support for Authenticated Mesh Peering Exchange
>> in userspace. ?The userspace daemon implements the AMPE protocol and on
>> successfull completion create mesh peers and install encryption keys.
>
> Do all combinations make sense? I mean, I can sort of see that you can
> have authenticated but unsecured, but secured and unauthenticated?

Probably not. I'm not 100% sure.

Javier

2011-05-03 23:57:45

by Javier Cardona

[permalink] [raw]
Subject: [PATCH 10/13] mac80211: Fix locking bug on mesh path table access

The mesh and mpp path tables are accessed from softirq and workqueue
context so non-irq locking cannot be used. Or at least that's what
PROVE_RCU seems to tell us here:

[ 431.240946] =================================
[ 431.241061] [ INFO: inconsistent lock state ]
[ 431.241061] 2.6.39-rc3-wl+ #354
[ 431.241061] ---------------------------------
[ 431.241061] inconsistent {IN-SOFTIRQ-W} -> {SOFTIRQ-ON-W} usage.
[ 431.241061] kworker/u:1/1423 [HC0[0]:SC0[0]:HE1:SE1] takes:
[ 431.241061] (&(&newtbl->hashwlock[i])->rlock){+.?...}, at:
[<c14671bf>] mesh_path_add+0x167/0x257

Signed-off-by: Javier Cardona <[email protected]>
---
net/mac80211/mesh_pathtbl.c | 54 ++++++++++++++++++++++--------------------
1 files changed, 28 insertions(+), 26 deletions(-)

diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c
index d4e86fd..a1d59bd 100644
--- a/net/mac80211/mesh_pathtbl.c
+++ b/net/mac80211/mesh_pathtbl.c
@@ -55,12 +55,12 @@ void mesh_table_free(struct mesh_table *tbl, bool free_leafs)

mesh_hash = tbl->hash_buckets;
for (i = 0; i <= tbl->hash_mask; i++) {
- spin_lock(&tbl->hashwlock[i]);
+ spin_lock_bh(&tbl->hashwlock[i]);
hlist_for_each_safe(p, q, &mesh_hash[i]) {
tbl->free_node(p, free_leafs);
atomic_dec(&tbl->entries);
}
- spin_unlock(&tbl->hashwlock[i]);
+ spin_unlock_bh(&tbl->hashwlock[i]);
}
__mesh_table_free(tbl);
}
@@ -274,7 +274,7 @@ int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata)
if (!new_node)
goto err_node_alloc;

- read_lock(&pathtbl_resize_lock);
+ read_lock_bh(&pathtbl_resize_lock);
memcpy(new_mpath->dst, dst, ETH_ALEN);
new_mpath->sdata = sdata;
new_mpath->flags = 0;
@@ -289,7 +289,7 @@ int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata)
hash_idx = mesh_table_hash(dst, sdata, mesh_paths);
bucket = &mesh_paths->hash_buckets[hash_idx];

- spin_lock(&mesh_paths->hashwlock[hash_idx]);
+ spin_lock_bh(&mesh_paths->hashwlock[hash_idx]);

err = -EEXIST;
hlist_for_each_entry(node, n, bucket, list) {
@@ -305,8 +305,8 @@ int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata)

mesh_paths_generation++;

- spin_unlock(&mesh_paths->hashwlock[hash_idx]);
- read_unlock(&pathtbl_resize_lock);
+ spin_unlock_bh(&mesh_paths->hashwlock[hash_idx]);
+ read_unlock_bh(&pathtbl_resize_lock);
if (grow) {
set_bit(MESH_WORK_GROW_MPATH_TABLE, &ifmsh->wrkq_flags);
ieee80211_queue_work(&local->hw, &sdata->work);
@@ -314,8 +314,8 @@ int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata)
return 0;

err_exists:
- spin_unlock(&mesh_paths->hashwlock[hash_idx]);
- read_unlock(&pathtbl_resize_lock);
+ spin_unlock_bh(&mesh_paths->hashwlock[hash_idx]);
+ read_unlock_bh(&pathtbl_resize_lock);
kfree(new_node);
err_node_alloc:
kfree(new_mpath);
@@ -332,16 +332,17 @@ void mesh_mpath_table_grow(void)
newtbl = mesh_table_alloc(rcu_dereference(mesh_paths)->size_order + 1);
if (!newtbl)
return;
- write_lock(&pathtbl_resize_lock);
+ write_lock_bh(&pathtbl_resize_lock);
oldtbl = mesh_paths;
if (mesh_table_grow(mesh_paths, newtbl) < 0) {
+ rcu_read_unlock();
__mesh_table_free(newtbl);
- write_unlock(&pathtbl_resize_lock);
+ write_unlock_bh(&pathtbl_resize_lock);
return;
}
rcu_read_unlock();
rcu_assign_pointer(mesh_paths, newtbl);
- write_unlock(&pathtbl_resize_lock);
+ write_unlock_bh(&pathtbl_resize_lock);

synchronize_rcu();
mesh_table_free(oldtbl, false);
@@ -355,16 +356,17 @@ void mesh_mpp_table_grow(void)
newtbl = mesh_table_alloc(rcu_dereference(mpp_paths)->size_order + 1);
if (!newtbl)
return;
- write_lock(&pathtbl_resize_lock);
+ write_lock_bh(&pathtbl_resize_lock);
oldtbl = mpp_paths;
if (mesh_table_grow(mpp_paths, newtbl) < 0) {
+ rcu_read_unlock();
__mesh_table_free(newtbl);
- write_unlock(&pathtbl_resize_lock);
+ write_unlock_bh(&pathtbl_resize_lock);
return;
}
rcu_read_unlock();
rcu_assign_pointer(mpp_paths, newtbl);
- write_unlock(&pathtbl_resize_lock);
+ write_unlock_bh(&pathtbl_resize_lock);

synchronize_rcu();
mesh_table_free(oldtbl, false);
@@ -398,7 +400,7 @@ int mpp_path_add(u8 *dst, u8 *mpp, struct ieee80211_sub_if_data *sdata)
if (!new_node)
goto err_node_alloc;

- read_lock(&pathtbl_resize_lock);
+ read_lock_bh(&pathtbl_resize_lock);
memcpy(new_mpath->dst, dst, ETH_ALEN);
memcpy(new_mpath->mpp, mpp, ETH_ALEN);
new_mpath->sdata = sdata;
@@ -411,7 +413,7 @@ int mpp_path_add(u8 *dst, u8 *mpp, struct ieee80211_sub_if_data *sdata)
hash_idx = mesh_table_hash(dst, sdata, mpp_paths);
bucket = &mpp_paths->hash_buckets[hash_idx];

- spin_lock(&mpp_paths->hashwlock[hash_idx]);
+ spin_lock_bh(&mpp_paths->hashwlock[hash_idx]);

err = -EEXIST;
hlist_for_each_entry(node, n, bucket, list) {
@@ -425,8 +427,8 @@ int mpp_path_add(u8 *dst, u8 *mpp, struct ieee80211_sub_if_data *sdata)
mpp_paths->mean_chain_len * (mpp_paths->hash_mask + 1))
grow = 1;

- spin_unlock(&mpp_paths->hashwlock[hash_idx]);
- read_unlock(&pathtbl_resize_lock);
+ spin_unlock_bh(&mpp_paths->hashwlock[hash_idx]);
+ read_unlock_bh(&pathtbl_resize_lock);
if (grow) {
set_bit(MESH_WORK_GROW_MPP_TABLE, &ifmsh->wrkq_flags);
ieee80211_queue_work(&local->hw, &sdata->work);
@@ -434,8 +436,8 @@ int mpp_path_add(u8 *dst, u8 *mpp, struct ieee80211_sub_if_data *sdata)
return 0;

err_exists:
- spin_unlock(&mpp_paths->hashwlock[hash_idx]);
- read_unlock(&pathtbl_resize_lock);
+ spin_unlock_bh(&mpp_paths->hashwlock[hash_idx]);
+ read_unlock_bh(&pathtbl_resize_lock);
kfree(new_node);
err_node_alloc:
kfree(new_mpath);
@@ -548,11 +550,11 @@ int mesh_path_del(u8 *addr, struct ieee80211_sub_if_data *sdata)
int hash_idx;
int err = 0;

- read_lock(&pathtbl_resize_lock);
+ read_lock_bh(&pathtbl_resize_lock);
hash_idx = mesh_table_hash(addr, sdata, mesh_paths);
bucket = &mesh_paths->hash_buckets[hash_idx];

- spin_lock(&mesh_paths->hashwlock[hash_idx]);
+ spin_lock_bh(&mesh_paths->hashwlock[hash_idx]);
hlist_for_each_entry(node, n, bucket, list) {
mpath = node->mpath;
if (mpath->sdata == sdata &&
@@ -570,8 +572,8 @@ int mesh_path_del(u8 *addr, struct ieee80211_sub_if_data *sdata)
err = -ENXIO;
enddel:
mesh_paths_generation++;
- spin_unlock(&mesh_paths->hashwlock[hash_idx]);
- read_unlock(&pathtbl_resize_lock);
+ spin_unlock_bh(&mesh_paths->hashwlock[hash_idx]);
+ read_unlock_bh(&pathtbl_resize_lock);
return err;
}

@@ -723,7 +725,7 @@ void mesh_path_expire(struct ieee80211_sub_if_data *sdata)
struct hlist_node *p;
int i;

- read_lock(&pathtbl_resize_lock);
+ read_lock_bh(&pathtbl_resize_lock);
for_each_mesh_entry(mesh_paths, p, node, i) {
if (node->mpath->sdata != sdata)
continue;
@@ -738,7 +740,7 @@ void mesh_path_expire(struct ieee80211_sub_if_data *sdata)
} else
spin_unlock_bh(&mpath->state_lock);
}
- read_unlock(&pathtbl_resize_lock);
+ read_unlock_bh(&pathtbl_resize_lock);
}

void mesh_pathtbl_unregister(void)
--
1.7.1


2011-05-03 23:57:47

by Javier Cardona

[permalink] [raw]
Subject: [PATCH 12/13] mac80211: allow setting supported rates on mesh peers

This is necessary for userspace managed stations.

Signed-off-by: Javier Cardona <[email protected]>
---
net/wireless/nl80211.c | 2 --
1 files changed, 0 insertions(+), 2 deletions(-)

diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index da1cdbe..afc07df 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -2293,8 +2293,6 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
err = -EINVAL;
if (params.listen_interval >= 0)
err = -EINVAL;
- if (params.supported_rates)
- err = -EINVAL;
if (params.sta_flags_mask &
~(BIT(NL80211_STA_FLAG_AUTHENTICATED) |
BIT(NL80211_STA_FLAG_MFP) |
--
1.7.1


2011-05-04 12:27:54

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH 01/13] nl80211: Introduce NL80211_MESH_SETUP_USERSPACE_AMPE

On Tue, 2011-05-03 at 16:57 -0700, Javier Cardona wrote:

> These patches introduce support for Authenticated Mesh Peering Exchange
> in userspace. The userspace daemon implements the AMPE protocol and on
> successfull completion create mesh peers and install encryption keys.

Do all combinations make sense? I mean, I can sort of see that you can
have authenticated but unsecured, but secured and unauthenticated?

johannes


2011-05-04 17:25:07

by Javier Cardona

[permalink] [raw]
Subject: [PATCH] cfg80211: Use capability info to detect mesh beacons.

Mesh beacons no longer use all-zeroes BSSID. Beacon frames for MBSS,
infrastructure BSS, or IBSS are differentiated by the Capability
Information field in the Beacon frame. A mesh STA sets the ESS and IBSS
subfields to 0 in transmitted Beacon or Probe Response management
frames.

Signed-off-by: Javier Cardona <[email protected]>
---
include/linux/ieee80211.h | 5 +++++
net/wireless/scan.c | 14 +++++++-------
2 files changed, 12 insertions(+), 7 deletions(-)

diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index a26dcb8..b2eee58 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -1002,6 +1002,11 @@ struct ieee80211_ht_info {

#define WLAN_CAPABILITY_ESS (1<<0)
#define WLAN_CAPABILITY_IBSS (1<<1)
+
+/* A mesh STA sets the ESS and IBSS capability bits to zero */
+#define WLAN_CAPABILITY_IS_MBSS(cap) \
+ (!((cap) & (WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_IBSS)))
+
#define WLAN_CAPABILITY_CF_POLLABLE (1<<2)
#define WLAN_CAPABILITY_CF_POLL_REQUEST (1<<3)
#define WLAN_CAPABILITY_PRIVACY (1<<4)
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index fbf6f33..62e542a 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -210,7 +210,7 @@ static bool is_mesh(struct cfg80211_bss *a,
{
const u8 *ie;

- if (!is_zero_ether_addr(a->bssid))
+ if (!WLAN_CAPABILITY_IS_MBSS(a->capability))
return false;

ie = cfg80211_find_ie(WLAN_EID_MESH_ID,
@@ -248,11 +248,7 @@ static int cmp_bss(struct cfg80211_bss *a,
if (a->channel != b->channel)
return b->channel->center_freq - a->channel->center_freq;

- r = memcmp(a->bssid, b->bssid, ETH_ALEN);
- if (r)
- return r;
-
- if (is_zero_ether_addr(a->bssid)) {
+ if (WLAN_CAPABILITY_IS_MBSS(a->capability | b->capability)) {
r = cmp_ies(WLAN_EID_MESH_ID,
a->information_elements,
a->len_information_elements,
@@ -267,6 +263,10 @@ static int cmp_bss(struct cfg80211_bss *a,
b->len_information_elements);
}

+ r = memcmp(a->bssid, b->bssid, ETH_ALEN);
+ if (r)
+ return r;
+
return cmp_ies(WLAN_EID_SSID,
a->information_elements,
a->len_information_elements,
@@ -407,7 +407,7 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev,

res->ts = jiffies;

- if (is_zero_ether_addr(res->pub.bssid)) {
+ if (WLAN_CAPABILITY_IS_MBSS(res->pub.capability)) {
/* must be mesh, verify */
meshid = cfg80211_find_ie(WLAN_EID_MESH_ID,
res->pub.information_elements,
--
1.7.1


2011-05-31 17:27:11

by Javier Cardona

[permalink] [raw]
Subject: Re: [PATCH] cfg80211: Use capability info to detect mesh beacons.

On Mon, May 30, 2011 at 3:51 AM, Vivek Natarajan <[email protected]> wrote:
> On Wed, May 4, 2011 at 10:54 PM, Javier Cardona <[email protected]> wrote:
>> Mesh beacons no longer use all-zeroes BSSID. ?Beacon frames for MBSS,
>> infrastructure BSS, or IBSS are differentiated by the Capability
>> Information field in the Beacon frame. ?A mesh STA sets the ESS and IBSS
>> subfields to 0 in transmitted Beacon or Probe Response management
>> frames.
>
> This breaks P2P mode as a P2P STA also sets the ESS and IBSS subfields
> to zero. Is there any other way to find if it is a mesh other than
> this check?

Bummer. I guess that's a collision between WiFi Alliance and IEEE,
respectively the organizations standardizing P2P and 802.11s.
The 11s draft is pretty clear about that. I can consult the task
group and see if they have thought about this conflict.

>> index fbf6f33..62e542a 100644
>> --- a/net/wireless/scan.c
>> +++ b/net/wireless/scan.c
>
>> @@ -407,7 +407,7 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev,
>>
>> ? ? ? ?res->ts = jiffies;
>>
>> - ? ? ? if (is_zero_ether_addr(res->pub.bssid)) {
>> + ? ? ? if (WLAN_CAPABILITY_IS_MBSS(res->pub.capability)) {
>> ? ? ? ? ? ? ? ?/* must be mesh, verify */
>
> Reverting the above change, makes P2P work. Any other better fix?

We could check that the WLAN_CAPABILITY_IS_MBSS *and* that the bssid
matches the TA. Do you think that would work?

Thanks,

Javier



--
Javier Cardona
cozybit Inc.
http://www.cozybit.com

2011-05-04 12:29:03

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH 05/13] nl80211: Let userspace drive the peer link management states.

On Tue, 2011-05-03 at 16:57 -0700, Javier Cardona wrote:

> +++ b/include/linux/nl80211.h
> @@ -902,6 +902,9 @@ enum nl80211_commands {
> * @NL80211_ATTR_SUPPORT_MESH_AUTH: Currently, this means the underlying driver
> * allows auth frames in a mesh to be passed to userspace for processing via
> * the @NL80211_MESH_SETUP_USERSPACE_AUTH flag.
> + * @NL80211_ATTR_STA_PLINK_STATE: The state of a mesh peer link. Used when
> + * userspace is driving the peer link management state machine.
> + * @NL80211_MESH_SETUP_USERSPACE_AMPE must be enabled.

What values are contained in this field?


> +++ b/include/net/cfg80211.h
> @@ -372,6 +372,33 @@ enum plink_actions {
> };
>
> /**
> + * enum plink_states - state of a mesh peer link finite state machine

Looks like you want these, but they're definitely in the wrong file
then.

johannes


2011-05-03 23:57:43

by Javier Cardona

[permalink] [raw]
Subject: [PATCH 09/13] Check size of a new mesh path table for changes since allocation.

Not sure if I'm chasing a ghost here, seems like the
mesh_path->size_order needs to be inside an RCU-read section to prevent
that value from changing between table allocation and copying. We have
observed crashes that might be caused by this.

Signed-off-by: Javier Cardona <[email protected]>
---
net/mac80211/mesh_pathtbl.c | 9 ++++++---
1 files changed, 6 insertions(+), 3 deletions(-)

diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c
index 35c715a..d4e86fd 100644
--- a/net/mac80211/mesh_pathtbl.c
+++ b/net/mac80211/mesh_pathtbl.c
@@ -76,7 +76,6 @@ static int mesh_table_grow(struct mesh_table *oldtbl,
< oldtbl->mean_chain_len * (oldtbl->hash_mask + 1))
return -EAGAIN;

-
newtbl->free_node = oldtbl->free_node;
newtbl->mean_chain_len = oldtbl->mean_chain_len;
newtbl->copy_node = oldtbl->copy_node;
@@ -329,7 +328,8 @@ void mesh_mpath_table_grow(void)
{
struct mesh_table *oldtbl, *newtbl;

- newtbl = mesh_table_alloc(mesh_paths->size_order + 1);
+ rcu_read_lock();
+ newtbl = mesh_table_alloc(rcu_dereference(mesh_paths)->size_order + 1);
if (!newtbl)
return;
write_lock(&pathtbl_resize_lock);
@@ -339,6 +339,7 @@ void mesh_mpath_table_grow(void)
write_unlock(&pathtbl_resize_lock);
return;
}
+ rcu_read_unlock();
rcu_assign_pointer(mesh_paths, newtbl);
write_unlock(&pathtbl_resize_lock);

@@ -350,7 +351,8 @@ void mesh_mpp_table_grow(void)
{
struct mesh_table *oldtbl, *newtbl;

- newtbl = mesh_table_alloc(mpp_paths->size_order + 1);
+ rcu_read_lock();
+ newtbl = mesh_table_alloc(rcu_dereference(mpp_paths)->size_order + 1);
if (!newtbl)
return;
write_lock(&pathtbl_resize_lock);
@@ -360,6 +362,7 @@ void mesh_mpp_table_grow(void)
write_unlock(&pathtbl_resize_lock);
return;
}
+ rcu_read_unlock();
rcu_assign_pointer(mpp_paths, newtbl);
write_unlock(&pathtbl_resize_lock);

--
1.7.1


2011-05-04 12:57:58

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH 04/13] open80211s: Stop using zero for address 3 in mesh plink mgmt frames

On Tue, 2011-05-03 at 16:57 -0700, Javier Cardona wrote:
> Previous versions of 11s draft used the all zeroes address. Current
> draft uses the same address as address 2.

There's also some code in net/wireless/scan.c that should be removed or
changed then I think?

johannes


2011-05-30 10:51:24

by Vivek Natarajan

[permalink] [raw]
Subject: Re: [PATCH] cfg80211: Use capability info to detect mesh beacons.

On Wed, May 4, 2011 at 10:54 PM, Javier Cardona <[email protected]> wrote:
> Mesh beacons no longer use all-zeroes BSSID. ?Beacon frames for MBSS,
> infrastructure BSS, or IBSS are differentiated by the Capability
> Information field in the Beacon frame. ?A mesh STA sets the ESS and IBSS
> subfields to 0 in transmitted Beacon or Probe Response management
> frames.

This breaks P2P mode as a P2P STA also sets the ESS and IBSS subfields
to zero. Is there any other way to find if it is a mesh other than
this check?

> index fbf6f33..62e542a 100644
> --- a/net/wireless/scan.c
> +++ b/net/wireless/scan.c

> @@ -407,7 +407,7 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev,
>
> ? ? ? ?res->ts = jiffies;
>
> - ? ? ? if (is_zero_ether_addr(res->pub.bssid)) {
> + ? ? ? if (WLAN_CAPABILITY_IS_MBSS(res->pub.capability)) {
> ? ? ? ? ? ? ? ?/* must be mesh, verify */

Reverting the above change, makes P2P work. Any other better fix?

> ? ? ? ? ? ? ? ?meshid = cfg80211_find_ie(WLAN_EID_MESH_ID,
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?res->pub.information_elements,
> --

Vivek.

2011-05-04 17:31:54

by Javier Cardona

[permalink] [raw]
Subject: Re: [PATCH 13/13] ath9k: fix beaconing for mesh interfaces

On Wed, May 4, 2011 at 10:25 AM, Johannes Berg
<[email protected]> wrote:
> On Wed, 2011-05-04 at 10:13 -0700, Javier Cardona wrote:
>
>> The current version of the draft defines a different beaconing mode
>> specific for mesh.
>
> Out of curiosity, what does that mode look like?

Similar to AP mode (fixed beaconing period) but with a mechanism to
avoid collisions (Mesh Beaconing Collision Avoidance).

Javier

2011-05-03 23:57:31

by Javier Cardona

[permalink] [raw]
Subject: [PATCH 01/13] nl80211: Introduce NL80211_MESH_SETUP_USERSPACE_AMPE

Introduce a new configuration option to support AMPE from userspace.

Prior to this series we only supported authentication in userspace: an
authentication daemon would authenticate peer candidates in userspace
and hand them over to the kernel. From that point the mesh stack would
take over and establish a peer link (Mesh Peering Management).

These patches introduce support for Authenticated Mesh Peering Exchange
in userspace. The userspace daemon implements the AMPE protocol and on
successfull completion create mesh peers and install encryption keys.

Signed-off-by: Javier Cardona <[email protected]>
---
include/linux/nl80211.h | 10 ++++++++++
include/net/cfg80211.h | 4 +++-
net/mac80211/cfg.c | 6 +++++-
net/mac80211/ieee80211_i.h | 6 +++++-
net/mac80211/mesh.c | 2 +-
net/mac80211/mesh_plink.c | 5 +++--
net/wireless/nl80211.c | 4 +++-
7 files changed, 30 insertions(+), 7 deletions(-)

diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index 216b1d8..8684c0a 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -1748,6 +1748,15 @@ enum nl80211_meshconf_params {
* @NL80211_MESH_SETUP_USERSPACE_AUTH: Enable this option if an authentication
* daemon will be authenticating mesh candidates.
*
+ * @NL80211_MESH_SETUP_USERSPACE_AMPE: Enable this option if an authentication
+ * daemon will be securing peer link frames. AMPE is a secured version of Mesh
+ * Peering Management (MPM) and is implemented with the assistance of a
+ * userspace daemon. When this flag is set, the kernel will send peer
+ * management frames to a userspace daemon that will implement AMPE
+ * functionality (security capabilities selection, key confirmation, and key
+ * management). When the flag is unset (default), the kernel can autonomously
+ * complete (unsecured) mesh peering without the need of a userspace daemon.
+ *
* @NL80211_MESH_SETUP_ATTR_MAX: highest possible mesh setup attribute number
* @__NL80211_MESH_SETUP_ATTR_AFTER_LAST: Internal use
*/
@@ -1757,6 +1766,7 @@ enum nl80211_mesh_setup_params {
NL80211_MESH_SETUP_ENABLE_VENDOR_METRIC,
NL80211_MESH_SETUP_IE,
NL80211_MESH_SETUP_USERSPACE_AUTH,
+ NL80211_MESH_SETUP_USERSPACE_AMPE,

/* keep last */
__NL80211_MESH_SETUP_ATTR_AFTER_LAST,
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index d30eada..5e4f87b 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -695,7 +695,8 @@ struct mesh_config {
* @path_metric: which metric to use
* @ie: vendor information elements (optional)
* @ie_len: length of vendor information elements
- * @is_secure: or not
+ * @is_authenticated: this mesh requires authentication
+ * @is_secure: this mesh uses security
*
* These parameters are fixed when the mesh is created.
*/
@@ -706,6 +707,7 @@ struct mesh_setup {
u8 path_metric;
const u8 *ie;
u8 ie_len;
+ bool is_authenticated;
bool is_secure;
};

diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 12d52ce..7ea13d3 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1064,7 +1064,11 @@ static int copy_mesh_setup(struct ieee80211_if_mesh *ifmsh,
memcpy(ifmsh->mesh_id, setup->mesh_id, ifmsh->mesh_id_len);
ifmsh->mesh_pp_id = setup->path_sel_proto;
ifmsh->mesh_pm_id = setup->path_metric;
- ifmsh->is_secure = setup->is_secure;
+ ifmsh->security = IEEE80211_MESH_SEC_NONE;
+ if (setup->is_authenticated)
+ ifmsh->security |= IEEE80211_MESH_SEC_AUTHED;
+ if (setup->is_secure)
+ ifmsh->security |= IEEE80211_MESH_SEC_SECURED;

return 0;
}
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 027c046..ec360fb 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -490,7 +490,11 @@ struct ieee80211_if_mesh {
bool accepting_plinks;
const u8 *ie;
u8 ie_len;
- bool is_secure;
+ enum {
+ IEEE80211_MESH_SEC_NONE = 0x0,
+ IEEE80211_MESH_SEC_AUTHED = 0x1,
+ IEEE80211_MESH_SEC_SECURED = 0x2,
+ } security;
};

#ifdef CONFIG_MAC80211_MESH
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index c1299e2..2a59eb3 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -574,7 +574,7 @@ static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata,
&elems);

/* ignore beacons from secure mesh peers if our security is off */
- if (elems.rsn_len && !sdata->u.mesh.is_secure)
+ if (elems.rsn_len && sdata->u.mesh.security == IEEE80211_MESH_SEC_NONE)
return;

if (elems.ds_params && elems.ds_params_len == 1)
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c
index 84e5b05..87abf8d 100644
--- a/net/mac80211/mesh_plink.c
+++ b/net/mac80211/mesh_plink.c
@@ -251,7 +251,7 @@ void mesh_neighbour_update(u8 *hw_addr, u32 rates,
rcu_read_unlock();
/* Userspace handles peer allocation when security is enabled
* */
- if (sdata->u.mesh.is_secure)
+ if (sdata->u.mesh.security & IEEE80211_MESH_SEC_AUTHED)
cfg80211_notify_new_peer_candidate(sdata->dev, hw_addr,
elems->ie_start, elems->total_len,
GFP_KERNEL);
@@ -460,7 +460,8 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
mpl_dbg("Mesh plink: missing necessary peer link ie\n");
return;
}
- if (elems.rsn_len && !sdata->u.mesh.is_secure) {
+ if (elems.rsn_len &&
+ sdata->u.mesh.security == IEEE80211_MESH_SEC_NONE) {
mpl_dbg("Mesh plink: can't establish link with secure peer\n");
return;
}
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 0efa7fd..7c1c4de 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -2840,6 +2840,7 @@ static const struct nla_policy
[NL80211_MESH_SETUP_USERSPACE_AUTH] = { .type = NLA_FLAG },
[NL80211_MESH_SETUP_IE] = { .type = NLA_BINARY,
.len = IEEE80211_MAX_DATA_LEN },
+ [NL80211_MESH_SETUP_USERSPACE_AMPE] = { .type = NLA_FLAG },
};

static int nl80211_parse_mesh_config(struct genl_info *info,
@@ -2949,7 +2950,8 @@ static int nl80211_parse_mesh_setup(struct genl_info *info,
setup->ie = nla_data(ieattr);
setup->ie_len = nla_len(ieattr);
}
- setup->is_secure = nla_get_flag(tb[NL80211_MESH_SETUP_USERSPACE_AUTH]);
+ setup->is_authenticated = nla_get_flag(tb[NL80211_MESH_SETUP_USERSPACE_AUTH]);
+ setup->is_secure = nla_get_flag(tb[NL80211_MESH_SETUP_USERSPACE_AMPE]);

return 0;
}
--
1.7.1


2011-05-04 17:14:17

by Javier Cardona

[permalink] [raw]
Subject: Re: [PATCH 13/13] ath9k: fix beaconing for mesh interfaces

On Wed, May 4, 2011 at 7:42 AM, Felix Fietkau <[email protected]> wrote:
> On 2011-05-04 1:57 AM, Javier Cardona wrote:
>>
>> Mesh beaconing on ath9k was broken by this commit:
>>
>> commit 4801416c76a3a355076d6d371c00270dfe332e1c
>> Author: Ben Greear<[email protected]>
>> Date: ? Sat Jan 15 19:13:48 2011 +0000
>>
>> This patch assigns the right opmode when the device is used in mesh
>> mode.
>>
>> Reported-by: Fabrice Deyber [email protected]
>> Signed-off-by: Javier Cardona<[email protected]>
>
> Any idea why exactly ath9k needs to use this opmode? If I understand the
> specs correctly, 802.11s does not use distributed beacons like ad-hoc mode,
> so theoretically it should be fine with using the AP iftype.
> If beacons don't work at all in this opmode for 802.11s then this patch may
> just be covering up an underlying bug rather than fixing the real issue.

Older versions of the 11s draft let implementers decide whether mesh
nodes would beacon in ad-hoc or AP mode. Apparently on ath9k ad-hoc
mode was chosen when the earlier mesh draft was implemented.

The current version of the draft defines a different beaconing mode
specific for mesh. This is very unlikely to change since 11s has
already passed sponsor ballot. My suggestion would be to keep using
ad-hoc style beaconing in ath9k for mesh and to leave the opmode
around for when mesh-specific beaconing is implemented in the driver.

But I know little about ath9k. If someone can suggest a better way to
"unbreak" mesh beaconing I'll be equally happy.

Thanks!

Javier

2011-05-04 16:28:36

by Javier Cardona

[permalink] [raw]
Subject: Re: [PATCH 04/13] open80211s: Stop using zero for address 3 in mesh plink mgmt frames

On Wed, May 4, 2011 at 5:57 AM, Johannes Berg <[email protected]> wrote:
> On Tue, 2011-05-03 at 16:57 -0700, Javier Cardona wrote:
>> Previous versions of 11s draft used the all zeroes address. ?Current
>> draft uses the same address as address 2.
>
> There's also some code in net/wireless/scan.c that should be removed or
> changed then I think?

Ah, I see:

if (is_zero_ether_addr(res->pub.bssid)) {
/* must be mesh, verify */
meshid = cfg80211_find_ie(WLAN_EID_MESH_ID,
res->pub.information_elements,
res->pub.len_information_elements);

I'll review that file and send send a follow up patch.

Thanks,

Javier

2011-05-03 23:57:49

by Javier Cardona

[permalink] [raw]
Subject: [PATCH 13/13] ath9k: fix beaconing for mesh interfaces

Mesh beaconing on ath9k was broken by this commit:

commit 4801416c76a3a355076d6d371c00270dfe332e1c
Author: Ben Greear <[email protected]>
Date: Sat Jan 15 19:13:48 2011 +0000

This patch assigns the right opmode when the device is used in mesh
mode.

Reported-by: Fabrice Deyber [email protected]
Signed-off-by: Javier Cardona <[email protected]>
---
drivers/net/wireless/ath/ath9k/main.c | 4 +++-
1 files changed, 3 insertions(+), 1 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index c3dbf26..8fa07aa 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -1384,7 +1384,9 @@ static void ath9k_calculate_summary_state(struct ieee80211_hw *hw,
ath9k_hw_set_tsfadjust(ah, 0);
sc->sc_flags &= ~SC_OP_TSF_RESET;

- if (iter_data.nwds + iter_data.nmeshes)
+ if (iter_data.nmeshes)
+ ah->opmode = NL80211_IFTYPE_MESH_POINT;
+ else if (iter_data.nwds)
ah->opmode = NL80211_IFTYPE_AP;
else if (iter_data.nadhocs)
ah->opmode = NL80211_IFTYPE_ADHOC;
--
1.7.1


2011-05-31 18:10:18

by Eliad Peller

[permalink] [raw]
Subject: Re: [PATCH] cfg80211: Use capability info to detect mesh beacons.

On Tue, May 31, 2011 at 8:26 PM, Javier Cardona <[email protected]> wrote:
> On Mon, May 30, 2011 at 3:51 AM, Vivek Natarajan <[email protected]> wrote:
>> On Wed, May 4, 2011 at 10:54 PM, Javier Cardona <[email protected]> wrote:
>>> Mesh beacons no longer use all-zeroes BSSID. ?Beacon frames for MBSS,
>>> infrastructure BSS, or IBSS are differentiated by the Capability
>>> Information field in the Beacon frame. ?A mesh STA sets the ESS and IBSS
>>> subfields to 0 in transmitted Beacon or Probe Response management
>>> frames.
>>
>> This breaks P2P mode as a P2P STA also sets the ESS and IBSS subfields
>> to zero. Is there any other way to find if it is a mesh other than
>> this check?
>
> Bummer. ?I guess that's a collision between WiFi Alliance and IEEE,
> respectively the organizations standardizing P2P and 802.11s.
> The 11s draft is pretty clear about that. ?I can consult the task
> group and see if they have thought about this conflict.
>
>>> index fbf6f33..62e542a 100644
>>> --- a/net/wireless/scan.c
>>> +++ b/net/wireless/scan.c
>>
>>> @@ -407,7 +407,7 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev,
>>>
>>> ? ? ? ?res->ts = jiffies;
>>>
>>> - ? ? ? if (is_zero_ether_addr(res->pub.bssid)) {
>>> + ? ? ? if (WLAN_CAPABILITY_IS_MBSS(res->pub.capability)) {
>>> ? ? ? ? ? ? ? ?/* must be mesh, verify */
>>
>> Reverting the above change, makes P2P work. Any other better fix?
>
> We could check that the WLAN_CAPABILITY_IS_MBSS *and* that the bssid
> matches the TA. ?Do you think that would work?
>
i guess you are referring to SA (rather than TA).
in that case, this solution is not enough, as SA==bssid also holds
true for the p2p probe responses (at least when a single vif is being
used).

btw, i've already submitted some workaround for this issue:
http://permalink.gmane.org/gmane.linux.kernel.wireless.general/70763

in case we won't find a better solution...

Eliad.

2011-05-31 18:38:38

by Javier Cardona

[permalink] [raw]
Subject: Re: [PATCH] cfg80211: Use capability info to detect mesh beacons.

On Tue, May 31, 2011 at 11:10 AM, Eliad Peller <[email protected]> wrote:
> On Tue, May 31, 2011 at 8:26 PM, Javier Cardona <[email protected]> wrote:
>> On Mon, May 30, 2011 at 3:51 AM, Vivek Natarajan <[email protected]> wrote:
>>> On Wed, May 4, 2011 at 10:54 PM, Javier Cardona <[email protected]> wrote:
>>>> Mesh beacons no longer use all-zeroes BSSID. ?Beacon frames for MBSS,
>>>> infrastructure BSS, or IBSS are differentiated by the Capability
>>>> Information field in the Beacon frame. ?A mesh STA sets the ESS and IBSS
>>>> subfields to 0 in transmitted Beacon or Probe Response management
>>>> frames.
>>>
>>> This breaks P2P mode as a P2P STA also sets the ESS and IBSS subfields
>>> to zero. Is there any other way to find if it is a mesh other than
>>> this check?
>>
>> Bummer. ?I guess that's a collision between WiFi Alliance and IEEE,
>> respectively the organizations standardizing P2P and 802.11s.
>> The 11s draft is pretty clear about that. ?I can consult the task
>> group and see if they have thought about this conflict.
>>
>>>> index fbf6f33..62e542a 100644
>>>> --- a/net/wireless/scan.c
>>>> +++ b/net/wireless/scan.c
>>>
>>>> @@ -407,7 +407,7 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev,
>>>>
>>>> ? ? ? ?res->ts = jiffies;
>>>>
>>>> - ? ? ? if (is_zero_ether_addr(res->pub.bssid)) {
>>>> + ? ? ? if (WLAN_CAPABILITY_IS_MBSS(res->pub.capability)) {
>>>> ? ? ? ? ? ? ? ?/* must be mesh, verify */
>>>
>>> Reverting the above change, makes P2P work. Any other better fix?
>>
>> We could check that the WLAN_CAPABILITY_IS_MBSS *and* that the bssid
>> matches the TA. ?Do you think that would work?
>>
> i guess you are referring to SA (rather than TA).
> in that case, this solution is not enough, as SA==bssid also holds
> true for the p2p probe responses (at least when a single vif is being
> used).

Yes, you are right, SA or Address 2 (11s changes the address field
definitions from DA, SA, BSSID to Address 1, 2 and 3). In mesh
management frames, Address 2 always equals Address 3. Is this also
the case for some P2P management frames?

> btw, i've already submitted some workaround for this issue:
> http://permalink.gmane.org/gmane.linux.kernel.wireless.general/70763
>
> in case we won't find a better solution...

OK. If the answer to my question above is yes, then I guess we'll
have to do it as you suggest. Thanks!

Javier

--
Javier Cardona
cozybit Inc.
http://www.cozybit.com

2011-05-04 16:16:50

by Steve Brown

[permalink] [raw]
Subject: Re: [PATCH 13/13] ath9k: fix beaconing for mesh interfaces

On Wed, 2011-05-04 at 16:42 +0200, Felix Fietkau wrote:
> On 2011-05-04 1:57 AM, Javier Cardona wrote:
> > Mesh beaconing on ath9k was broken by this commit:
> >
> > commit 4801416c76a3a355076d6d371c00270dfe332e1c
> > Author: Ben Greear<[email protected]>
> > Date: Sat Jan 15 19:13:48 2011 +0000
> >
> > This patch assigns the right opmode when the device is used in mesh
> > mode.
> >
> > Reported-by: Fabrice Deyber [email protected]
> > Signed-off-by: Javier Cardona<[email protected]>
> Any idea why exactly ath9k needs to use this opmode? If I understand the
> specs correctly, 802.11s does not use distributed beacons like ad-hoc
> mode, so theoretically it should be fine with using the AP iftype.
> If beacons don't work at all in this opmode for 802.11s then this patch
> may just be covering up an underlying bug rather than fixing the real issue.
>
> - Felix
> --
I'd tend to agree. I think the problem is in ath9k_allow_beacon_config
with the test about not configuring station vif's when in AP mode. I
think it's too restrictive.

Maybe something like:

* Can not configure station vif's beacon config
* while on AP opmode
*/
if ((sc->sc_ah->opmode == NL80211_IFTYPE_AP) &&
- (vif->type != NL80211_IFTYPE_AP)) {
+ ((vif->type == NL80211_IFTYPE_STATION) ||
+ (vif->type == NL80211_IFTYPE_ADHOC))) {

Steve



2011-05-09 08:25:44

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH] cfg80211: Use capability info to detect mesh beacons.

On Wed, 2011-05-04 at 10:24 -0700, Javier Cardona wrote:
> Mesh beacons no longer use all-zeroes BSSID. Beacon frames for MBSS,
> infrastructure BSS, or IBSS are differentiated by the Capability
> Information field in the Beacon frame. A mesh STA sets the ESS and IBSS
> subfields to 0 in transmitted Beacon or Probe Response management
> frames.

Sorry for the late reply, yeah, I think that looks good.

johannes

> Signed-off-by: Javier Cardona <[email protected]>
> ---
> include/linux/ieee80211.h | 5 +++++
> net/wireless/scan.c | 14 +++++++-------
> 2 files changed, 12 insertions(+), 7 deletions(-)
>
> diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
> index a26dcb8..b2eee58 100644
> --- a/include/linux/ieee80211.h
> +++ b/include/linux/ieee80211.h
> @@ -1002,6 +1002,11 @@ struct ieee80211_ht_info {
>
> #define WLAN_CAPABILITY_ESS (1<<0)
> #define WLAN_CAPABILITY_IBSS (1<<1)
> +
> +/* A mesh STA sets the ESS and IBSS capability bits to zero */
> +#define WLAN_CAPABILITY_IS_MBSS(cap) \
> + (!((cap) & (WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_IBSS)))
> +
> #define WLAN_CAPABILITY_CF_POLLABLE (1<<2)
> #define WLAN_CAPABILITY_CF_POLL_REQUEST (1<<3)
> #define WLAN_CAPABILITY_PRIVACY (1<<4)
> diff --git a/net/wireless/scan.c b/net/wireless/scan.c
> index fbf6f33..62e542a 100644
> --- a/net/wireless/scan.c
> +++ b/net/wireless/scan.c
> @@ -210,7 +210,7 @@ static bool is_mesh(struct cfg80211_bss *a,
> {
> const u8 *ie;
>
> - if (!is_zero_ether_addr(a->bssid))
> + if (!WLAN_CAPABILITY_IS_MBSS(a->capability))
> return false;
>
> ie = cfg80211_find_ie(WLAN_EID_MESH_ID,
> @@ -248,11 +248,7 @@ static int cmp_bss(struct cfg80211_bss *a,
> if (a->channel != b->channel)
> return b->channel->center_freq - a->channel->center_freq;
>
> - r = memcmp(a->bssid, b->bssid, ETH_ALEN);
> - if (r)
> - return r;
> -
> - if (is_zero_ether_addr(a->bssid)) {
> + if (WLAN_CAPABILITY_IS_MBSS(a->capability | b->capability)) {
> r = cmp_ies(WLAN_EID_MESH_ID,
> a->information_elements,
> a->len_information_elements,
> @@ -267,6 +263,10 @@ static int cmp_bss(struct cfg80211_bss *a,
> b->len_information_elements);
> }
>
> + r = memcmp(a->bssid, b->bssid, ETH_ALEN);
> + if (r)
> + return r;
> +
> return cmp_ies(WLAN_EID_SSID,
> a->information_elements,
> a->len_information_elements,
> @@ -407,7 +407,7 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev,
>
> res->ts = jiffies;
>
> - if (is_zero_ether_addr(res->pub.bssid)) {
> + if (WLAN_CAPABILITY_IS_MBSS(res->pub.capability)) {
> /* must be mesh, verify */
> meshid = cfg80211_find_ie(WLAN_EID_MESH_ID,
> res->pub.information_elements,



2011-05-03 23:57:46

by Javier Cardona

[permalink] [raw]
Subject: [PATCH 11/13] mac80211: Move call to mpp_path_lookup inside RCU-read section

PROVE_RCU caught that one:

[ 431.214070] ===================================================
[ 431.215341] [ INFO: suspicious rcu_dereference_check() usage. ]
[ 431.215674] ---------------------------------------------------
[ 431.216043] net/mac80211/mesh_pathtbl.c:184 invoked
rcu_dereference_check() without protection!

Signed-off-by: Javier Cardona <[email protected]>
---
net/mac80211/tx.c | 3 ++-
1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index e3e3aa1..8b20d08 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -1751,6 +1751,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
ret = NETDEV_TX_OK;
goto fail;
}
+ rcu_read_lock();
if (!is_multicast_ether_addr(skb->data))
mppath = mpp_path_lookup(skb->data, sdata);

@@ -1765,13 +1766,13 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
!(mppath && compare_ether_addr(mppath->mpp, skb->data))) {
hdrlen = ieee80211_fill_mesh_addresses(&hdr, &fc,
skb->data, skb->data + ETH_ALEN);
+ rcu_read_unlock();
meshhdrlen = ieee80211_new_mesh_header(&mesh_hdr,
sdata, NULL, NULL);
} else {
int is_mesh_mcast = 1;
const u8 *mesh_da;

- rcu_read_lock();
if (is_multicast_ether_addr(skb->data))
/* DA TA mSA AE:SA */
mesh_da = skb->data;
--
1.7.1


2011-05-04 16:34:36

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH 01/13] nl80211: Introduce NL80211_MESH_SETUP_USERSPACE_AMPE

On Wed, 2011-05-04 at 09:32 -0700, Javier Cardona wrote:
> On Wed, May 4, 2011 at 5:27 AM, Johannes Berg <[email protected]> wrote:
> > On Tue, 2011-05-03 at 16:57 -0700, Javier Cardona wrote:
> >
> >> These patches introduce support for Authenticated Mesh Peering Exchange
> >> in userspace. The userspace daemon implements the AMPE protocol and on
> >> successfull completion create mesh peers and install encryption keys.
> >
> > Do all combinations make sense? I mean, I can sort of see that you can
> > have authenticated but unsecured, but secured and unauthenticated?
>
> Probably not. I'm not 100% sure.

I was just wondering if it should be allowed at all.

johannes


2011-05-03 23:57:34

by Javier Cardona

[permalink] [raw]
Subject: [PATCH 03/13] mac80211: Drop MESH_PLINK category and use new ANA-approved MESH_ACTION

Note: This breaks compatibility with previous mesh protocol instances.

Signed-off-by: Javier Cardona <[email protected]>
---
include/linux/ieee80211.h | 5 ++---
net/mac80211/mesh.c | 2 +-
net/mac80211/mesh_plink.c | 2 +-
net/mac80211/rx.c | 7 +++++--
4 files changed, 9 insertions(+), 7 deletions(-)

diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index 79690b7..ee1c96a 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -1261,9 +1261,8 @@ enum ieee80211_category {
WLAN_CATEGORY_MULTIHOP_ACTION = 14,
WLAN_CATEGORY_SELF_PROTECTED = 15,
WLAN_CATEGORY_WMM = 17,
- /* TODO: remove MESH_PLINK and MESH_PATH_SEL after */
- /* mesh is updated to current 802.11s draft */
- WLAN_CATEGORY_MESH_PLINK = 30,
+ /* TODO: remove MESH_PATH_SEL after mesh is updated
+ * to current 802.11s draft */
WLAN_CATEGORY_MESH_PATH_SEL = 32,
WLAN_CATEGORY_VENDOR_SPECIFIC_PROTECTED = 126,
WLAN_CATEGORY_VENDOR_SPECIFIC = 127,
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index 2a59eb3..75378e8 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -600,7 +600,7 @@ static void ieee80211_mesh_rx_mgmt_action(struct ieee80211_sub_if_data *sdata,
struct ieee80211_rx_status *rx_status)
{
switch (mgmt->u.action.category) {
- case WLAN_CATEGORY_MESH_PLINK:
+ case WLAN_CATEGORY_MESH_ACTION:
mesh_rx_plink_frame(sdata, mgmt, len, rx_status);
break;
case WLAN_CATEGORY_MESH_PATH_SEL:
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c
index 87abf8d..0120e9e 100644
--- a/net/mac80211/mesh_plink.c
+++ b/net/mac80211/mesh_plink.c
@@ -182,7 +182,7 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
memcpy(mgmt->da, da, ETH_ALEN);
memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
/* BSSID is left zeroed, wildcard value */
- mgmt->u.action.category = WLAN_CATEGORY_MESH_PLINK;
+ mgmt->u.action.category = WLAN_CATEGORY_MESH_ACTION;
mgmt->u.action.u.plink_action.action_code = action;

if (action == PLINK_CLOSE)
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 13a6697..0f29bdb 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -495,8 +495,11 @@ ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx)
return RX_DROP_MONITOR;

if (ieee80211_is_action(hdr->frame_control)) {
+ u8 category;
mgmt = (struct ieee80211_mgmt *)hdr;
- if (mgmt->u.action.category != WLAN_CATEGORY_MESH_PLINK)
+ category = mgmt->u.action.category;
+ if (category != WLAN_CATEGORY_MESH_ACTION &&
+ category != WLAN_CATEGORY_SELF_PROTECTED)
return RX_DROP_MONITOR;
return RX_CONTINUE;
}
@@ -2205,7 +2208,7 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
goto handled;
}
break;
- case WLAN_CATEGORY_MESH_PLINK:
+ case WLAN_CATEGORY_MESH_ACTION:
if (!ieee80211_vif_is_mesh(&sdata->vif))
break;
goto queue;
--
1.7.1


2011-05-04 14:42:43

by Felix Fietkau

[permalink] [raw]
Subject: Re: [PATCH 13/13] ath9k: fix beaconing for mesh interfaces

On 2011-05-04 1:57 AM, Javier Cardona wrote:
> Mesh beaconing on ath9k was broken by this commit:
>
> commit 4801416c76a3a355076d6d371c00270dfe332e1c
> Author: Ben Greear<[email protected]>
> Date: Sat Jan 15 19:13:48 2011 +0000
>
> This patch assigns the right opmode when the device is used in mesh
> mode.
>
> Reported-by: Fabrice Deyber [email protected]
> Signed-off-by: Javier Cardona<[email protected]>
Any idea why exactly ath9k needs to use this opmode? If I understand the
specs correctly, 802.11s does not use distributed beacons like ad-hoc
mode, so theoretically it should be fine with using the AP iftype.
If beacons don't work at all in this opmode for 802.11s then this patch
may just be covering up an underlying bug rather than fixing the real issue.

- Felix

2011-05-03 23:57:40

by Javier Cardona

[permalink] [raw]
Subject: [PATCH 07/13] nl80211: allow setting MFP flag for a meshif

From: Thomas Pedersen <[email protected]>

Signed-off-by: Thomas Pedersen <[email protected]>
Signed-off-by: Javier Cardona <[email protected]>
---
net/wireless/nl80211.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 176d118..da1cdbe 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -2297,6 +2297,7 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
err = -EINVAL;
if (params.sta_flags_mask &
~(BIT(NL80211_STA_FLAG_AUTHENTICATED) |
+ BIT(NL80211_STA_FLAG_MFP) |
BIT(NL80211_STA_FLAG_AUTHORIZED)))
err = -EINVAL;
break;
--
1.7.1


2011-05-03 23:57:42

by Javier Cardona

[permalink] [raw]
Subject: [PATCH 08/13] mac80211: Self-protected management frames are not robust

From: Thomas Pedersen <[email protected]>

They may contain encrypted information elements (as AMPE frames do)
but they are not encrypted.

Signed-off-by: Thomas Pedersen <[email protected]>
Signed-off-by: Javier Cardona <[email protected]>
---
include/linux/ieee80211.h | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index ee1c96a..a26dcb8 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -1515,6 +1515,7 @@ static inline bool ieee80211_is_robust_mgmt_frame(struct ieee80211_hdr *hdr)
category = ((u8 *) hdr) + 24;
return *category != WLAN_CATEGORY_PUBLIC &&
*category != WLAN_CATEGORY_HT &&
+ *category != WLAN_CATEGORY_SELF_PROTECTED &&
*category != WLAN_CATEGORY_VENDOR_SPECIFIC;
}

--
1.7.1


2011-05-03 23:57:38

by Javier Cardona

[permalink] [raw]
Subject: [PATCH 05/13] nl80211: Let userspace drive the peer link management states.

Signed-off-by: Javier Cardona <[email protected]>
---
include/linux/nl80211.h | 4 ++++
include/net/cfg80211.h | 29 +++++++++++++++++++++++++++++
net/mac80211/cfg.c | 30 +++++++++++++++++++++---------
net/mac80211/sta_info.h | 23 -----------------------
net/wireless/nl80211.c | 6 ++++++
5 files changed, 60 insertions(+), 32 deletions(-)

diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index 8684c0a..48fb8cc 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -902,6 +902,9 @@ enum nl80211_commands {
* @NL80211_ATTR_SUPPORT_MESH_AUTH: Currently, this means the underlying driver
* allows auth frames in a mesh to be passed to userspace for processing via
* the @NL80211_MESH_SETUP_USERSPACE_AUTH flag.
+ * @NL80211_ATTR_STA_PLINK_STATE: The state of a mesh peer link. Used when
+ * userspace is driving the peer link management state machine.
+ * @NL80211_MESH_SETUP_USERSPACE_AMPE must be enabled.
*
* @NL80211_ATTR_MAX: highest attribute number currently defined
* @__NL80211_ATTR_AFTER_LAST: internal use
@@ -1091,6 +1094,7 @@ enum nl80211_attrs {
NL80211_ATTR_WIPHY_ANTENNA_AVAIL_RX,

NL80211_ATTR_SUPPORT_MESH_AUTH,
+ NL80211_ATTR_STA_PLINK_STATE,

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

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 5e4f87b..e956ffb 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -372,6 +372,33 @@ enum plink_actions {
};

/**
+ * enum plink_states - state of a mesh peer link finite state machine
+ *
+ * @PLINK_LISTEN: initial state, considered the implicit state of non
+ * existant mesh peer links
+ * @PLINK_OPN_SNT: mesh plink open frame has been sent to this mesh
+ * peer @PLINK_OPN_RCVD: mesh plink open frame has been received from
+ * this mesh peer
+ * @PLINK_CNF_RCVD: mesh plink confirm frame has been received from
+ * this mesh peer
+ * @PLINK_ESTAB: mesh peer link is established
+ * @PLINK_HOLDING: mesh peer link is being closed or cancelled
+ * @PLINK_BLOCKED: all frames transmitted from this mesh plink are
+ * discarded
+ * @PLINK_INVALID: reserved
+ */
+enum plink_state {
+ PLINK_LISTEN,
+ PLINK_OPN_SNT,
+ PLINK_OPN_RCVD,
+ PLINK_CNF_RCVD,
+ PLINK_ESTAB,
+ PLINK_HOLDING,
+ PLINK_BLOCKED,
+ PLINK_INVALID,
+};
+
+/**
* struct station_parameters - station parameters
*
* Used to change and create a new station.
@@ -387,6 +414,7 @@ enum plink_actions {
* @listen_interval: listen interval or -1 for no change
* @aid: AID or zero for no change
* @plink_action: plink action to take
+ * @plink_state: set the peer link state for a station
* @ht_capa: HT capabilities of station
*/
struct station_parameters {
@@ -397,6 +425,7 @@ struct station_parameters {
u16 aid;
u8 supported_rates_len;
u8 plink_action;
+ u8 plink_state;
struct ieee80211_ht_cap *ht_capa;
};

diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 7ea13d3..dbc5bcb 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -734,15 +734,27 @@ static void sta_apply_parameters(struct ieee80211_local *local,
params->ht_capa,
&sta->sta.ht_cap);

- if (ieee80211_vif_is_mesh(&sdata->vif) && params->plink_action) {
- switch (params->plink_action) {
- case PLINK_ACTION_OPEN:
- mesh_plink_open(sta);
- break;
- case PLINK_ACTION_BLOCK:
- mesh_plink_block(sta);
- break;
- }
+ if (ieee80211_vif_is_mesh(&sdata->vif)) {
+ if (sdata->u.mesh.security & IEEE80211_MESH_SEC_SECURED)
+ switch (params->plink_state) {
+ case PLINK_LISTEN:
+ case PLINK_ESTAB:
+ case PLINK_BLOCKED:
+ sta->plink_state = params->plink_state;
+ break;
+ default:
+ /* nothing */
+ break;
+ }
+ else
+ switch (params->plink_action) {
+ case PLINK_ACTION_OPEN:
+ mesh_plink_open(sta);
+ break;
+ case PLINK_ACTION_BLOCK:
+ mesh_plink_block(sta);
+ break;
+ }
}
}

diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index aa0adcb..f00b4dc 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -174,29 +174,6 @@ struct sta_ampdu_mlme {


/**
- * enum plink_state - state of a mesh peer link finite state machine
- *
- * @PLINK_LISTEN: initial state, considered the implicit state of non existent
- * mesh peer links
- * @PLINK_OPN_SNT: mesh plink open frame has been sent to this mesh peer
- * @PLINK_OPN_RCVD: mesh plink open frame has been received from this mesh peer
- * @PLINK_CNF_RCVD: mesh plink confirm frame has been received from this mesh
- * peer
- * @PLINK_ESTAB: mesh peer link is established
- * @PLINK_HOLDING: mesh peer link is being closed or cancelled
- * @PLINK_BLOCKED: all frames transmitted from this mesh plink are discarded
- */
-enum plink_state {
- PLINK_LISTEN,
- PLINK_OPN_SNT,
- PLINK_OPN_RCVD,
- PLINK_CNF_RCVD,
- PLINK_ESTAB,
- PLINK_HOLDING,
- PLINK_BLOCKED
-};
-
-/**
* struct sta_info - STA information
*
* This structure collects information about a station that
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 7c1c4de..49f220a 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -173,6 +173,7 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
[NL80211_ATTR_MCAST_RATE] = { .type = NLA_U32 },
[NL80211_ATTR_OFFCHANNEL_TX_OK] = { .type = NLA_FLAG },
[NL80211_ATTR_KEY_DEFAULT_TYPES] = { .type = NLA_NESTED },
+ [NL80211_ATTR_STA_PLINK_STATE] = { .type = NLA_U8 },
};

/* policy for the key attributes */
@@ -2216,6 +2217,7 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
memset(&params, 0, sizeof(params));

params.listen_interval = -1;
+ params.plink_state = PLINK_INVALID;

if (info->attrs[NL80211_ATTR_STA_AID])
return -EINVAL;
@@ -2247,6 +2249,10 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
params.plink_action =
nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]);

+ if (info->attrs[NL80211_ATTR_STA_PLINK_STATE])
+ params.plink_state =
+ nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_STATE]);
+
err = get_vlan(info, rdev, &params.vlan);
if (err)
goto out;
--
1.7.1


2011-06-01 07:01:50

by Eliad Peller

[permalink] [raw]
Subject: Re: [PATCH] cfg80211: Use capability info to detect mesh beacons.

On Tue, May 31, 2011 at 9:38 PM, Javier Cardona <[email protected]> wrote:
> On Tue, May 31, 2011 at 11:10 AM, Eliad Peller <[email protected]> wrote:
>> On Tue, May 31, 2011 at 8:26 PM, Javier Cardona <[email protected]> wrote:
>>> On Mon, May 30, 2011 at 3:51 AM, Vivek Natarajan <[email protected]> wrote:
>>>> On Wed, May 4, 2011 at 10:54 PM, Javier Cardona <[email protected]> wrote:
>>>>> Mesh beacons no longer use all-zeroes BSSID. ?Beacon frames for MBSS,
>>>>> infrastructure BSS, or IBSS are differentiated by the Capability
>>>>> Information field in the Beacon frame. ?A mesh STA sets the ESS and IBSS
>>>>> subfields to 0 in transmitted Beacon or Probe Response management
>>>>> frames.
>>>>
>>>> This breaks P2P mode as a P2P STA also sets the ESS and IBSS subfields
>>>> to zero. Is there any other way to find if it is a mesh other than
>>>> this check?
>>>
>>> Bummer. ?I guess that's a collision between WiFi Alliance and IEEE,
>>> respectively the organizations standardizing P2P and 802.11s.
>>> The 11s draft is pretty clear about that. ?I can consult the task
>>> group and see if they have thought about this conflict.
>>>
>>>>> index fbf6f33..62e542a 100644
>>>>> --- a/net/wireless/scan.c
>>>>> +++ b/net/wireless/scan.c
>>>>
>>>>> @@ -407,7 +407,7 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev,
>>>>>
>>>>> ? ? ? ?res->ts = jiffies;
>>>>>
>>>>> - ? ? ? if (is_zero_ether_addr(res->pub.bssid)) {
>>>>> + ? ? ? if (WLAN_CAPABILITY_IS_MBSS(res->pub.capability)) {
>>>>> ? ? ? ? ? ? ? ?/* must be mesh, verify */
>>>>
>>>> Reverting the above change, makes P2P work. Any other better fix?
>>>
>>> We could check that the WLAN_CAPABILITY_IS_MBSS *and* that the bssid
>>> matches the TA. ?Do you think that would work?
>>>
>> i guess you are referring to SA (rather than TA).
>> in that case, this solution is not enough, as SA==bssid also holds
>> true for the p2p probe responses (at least when a single vif is being
>> used).
>
> Yes, you are right, SA or Address 2 ?(11s changes the address field
> definitions from DA, SA, BSSID to Address 1, 2 and 3). ?In mesh
> management frames, Address 2 always equals Address 3. ?Is this also
> the case for some P2P management frames?
>
yes.

>> btw, i've already submitted some workaround for this issue:
>> http://permalink.gmane.org/gmane.linux.kernel.wireless.general/70763
>>
>> in case we won't find a better solution...
>
> OK. ?If the answer to my question above is yes, then I guess we'll
> have to do it as you suggest. ?Thanks!
ok. thanks.