2013-03-04 21:07:53

by Thomas Pedersen

[permalink] [raw]
Subject: [PATCH v2 1/5] nl80211: explicit userspace MPM

Secure mesh had the implicit requirement that the Mesh
Peering Management entity be in userspace. However
userspace might want to implement an open MPM as well, so
specify a mesh setup parameter to indicate this.

Signed-off-by: Thomas Pedersen <[email protected]>

---

v2:
reject setting userspace MPM if feature not
supported (Johannes)

include/net/cfg80211.h | 2 ++
include/uapi/linux/nl80211.h | 25 ++++++++++++++++++-------
net/wireless/mesh.c | 1 +
net/wireless/nl80211.c | 8 ++++++++
4 files changed, 29 insertions(+), 7 deletions(-)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 9b34c76..b6be55e 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -1151,6 +1151,7 @@ struct mesh_config {
* @ie_len: length of vendor information elements
* @is_authenticated: this mesh requires authentication
* @is_secure: this mesh uses security
+ * @user_mpm: userspace handles all MPM functions
* @dtim_period: DTIM period to use
* @beacon_interval: beacon interval to use
* @mcast_rate: multicat rate for Mesh Node [6Mbps is the default for 802.11a]
@@ -1168,6 +1169,7 @@ struct mesh_setup {
u8 ie_len;
bool is_authenticated;
bool is_secure;
+ bool user_mpm;
u8 dtim_period;
u16 beacon_interval;
int mcast_rate[IEEE80211_NUM_BANDS];
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 2d0cff5..8134c6a 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -513,9 +513,11 @@
* @NL80211_CMD_NEW_PEER_CANDIDATE: Notification on the reception of a
* beacon or probe response from a compatible mesh peer. This is only
* sent while no station information (sta_info) exists for the new peer
- * candidate and when @NL80211_MESH_SETUP_USERSPACE_AUTH is set. On
- * reception of this notification, userspace may decide to create a new
- * station (@NL80211_CMD_NEW_STATION). To stop this notification from
+ * candidate and when @NL80211_MESH_SETUP_USERSPACE_AUTH,
+ * @NL80211_MESH_SETUP_USERSPACE_AMPE, or
+ * @NL80211_MESH_SETUP_USERSPACE_MPM is set. On reception of this
+ * notification, userspace may decide to create a new station
+ * (@NL80211_CMD_NEW_STATION). To stop this notification from
* reoccurring, the userspace authentication daemon may want to create the
* new station with the AUTHENTICATED flag unset and maybe change it later
* depending on the authentication result.
@@ -1199,10 +1201,10 @@ 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 as
- * defined in &enum nl80211_plink_state. Used when userspace is
- * driving the peer link management state machine.
- * @NL80211_MESH_SETUP_USERSPACE_AMPE must be enabled.
+ * @NL80211_ATTR_STA_PLINK_STATE: The state of a mesh peer link as defined in
+ * &enum nl80211_plink_state. Used when userspace is driving the peer link
+ * management state machine. @NL80211_MESH_SETUP_USERSPACE_AMPE or
+ * @NL80211_MESH_SETUP_USERSPACE_MPM must be enabled.
*
* @NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED: indicates, as part of the wiphy
* capabilities, the supported WoWLAN triggers
@@ -2612,6 +2614,9 @@ enum nl80211_meshconf_params {
* vendor specific synchronization method or disable it to use the default
* neighbor offset synchronization
*
+ * @NL80211_MESH_SETUP_USERSPACE_MPM: Enable this option if userspace will
+ * implement an MPM which handles peer allocation and state.
+ *
* @NL80211_MESH_SETUP_ATTR_MAX: highest possible mesh setup attribute number
*
* @__NL80211_MESH_SETUP_ATTR_AFTER_LAST: Internal use
@@ -2624,6 +2629,7 @@ enum nl80211_mesh_setup_params {
NL80211_MESH_SETUP_USERSPACE_AUTH,
NL80211_MESH_SETUP_USERSPACE_AMPE,
NL80211_MESH_SETUP_ENABLE_VENDOR_SYNC,
+ NL80211_MESH_SETUP_USERSPACE_MPM,

/* keep last */
__NL80211_MESH_SETUP_ATTR_AFTER_LAST,
@@ -3526,6 +3532,10 @@ enum nl80211_ap_sme_features {
* stations the authenticated/associated bits have to be set in the mask.
* @NL80211_FEATURE_ADVERTISE_CHAN_LIMITS: cfg80211 advertises channel limits
* (HT40, VHT 80/160 MHz) if this flag is set
+ * @NL80211_FEATURE_USERSPACE_MPM: This driver supports a userspace Mesh
+ * Peering Management entity which may be implemented by registering for
+ * beacons or NL80211_CMD_NEW_PEER_CANDIDATE events. The mesh beacon is
+ * still generated by the driver.
*/
enum nl80211_feature_flags {
NL80211_FEATURE_SK_TX_STATUS = 1 << 0,
@@ -3544,6 +3554,7 @@ enum nl80211_feature_flags {
/* bit 13 is reserved */
NL80211_FEATURE_ADVERTISE_CHAN_LIMITS = 1 << 14,
NL80211_FEATURE_FULL_AP_CLIENT_STATE = 1 << 15,
+ NL80211_FEATURE_USERSPACE_MPM = 1 << 16,
};

/**
diff --git a/net/wireless/mesh.c b/net/wireless/mesh.c
index 9688b24..0bb93f3 100644
--- a/net/wireless/mesh.c
+++ b/net/wireless/mesh.c
@@ -85,6 +85,7 @@ const struct mesh_setup default_mesh_setup = {
.ie = NULL,
.ie_len = 0,
.is_secure = false,
+ .user_mpm = false,
.beacon_interval = MESH_DEFAULT_BEACON_INTERVAL,
.dtim_period = MESH_DEFAULT_DTIM_PERIOD,
};
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index c85a4b8..167fd83 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -4596,6 +4596,7 @@ static const struct nla_policy
[NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL] = { .type = NLA_U8 },
[NL80211_MESH_SETUP_ENABLE_VENDOR_METRIC] = { .type = NLA_U8 },
[NL80211_MESH_SETUP_USERSPACE_AUTH] = { .type = NLA_FLAG },
+ [NL80211_MESH_SETUP_USERSPACE_MPM] = { .type = NLA_FLAG },
[NL80211_MESH_SETUP_IE] = { .type = NLA_BINARY,
.len = IEEE80211_MAX_DATA_LEN },
[NL80211_MESH_SETUP_USERSPACE_AMPE] = { .type = NLA_FLAG },
@@ -4734,6 +4735,7 @@ do { \
static int nl80211_parse_mesh_setup(struct genl_info *info,
struct mesh_setup *setup)
{
+ struct cfg80211_registered_device *rdev = info->user_ptr[0];
struct nlattr *tb[NL80211_MESH_SETUP_ATTR_MAX + 1];

if (!info->attrs[NL80211_ATTR_MESH_SETUP])
@@ -4770,8 +4772,14 @@ static int nl80211_parse_mesh_setup(struct genl_info *info,
setup->ie = nla_data(ieattr);
setup->ie_len = nla_len(ieattr);
}
+ if (tb[NL80211_MESH_SETUP_USERSPACE_MPM] &&
+ !(rdev->wiphy.features & NL80211_FEATURE_USERSPACE_MPM))
+ return -EINVAL;
+ setup->user_mpm = nla_get_flag(tb[NL80211_MESH_SETUP_USERSPACE_MPM]);
setup->is_authenticated = nla_get_flag(tb[NL80211_MESH_SETUP_USERSPACE_AUTH]);
setup->is_secure = nla_get_flag(tb[NL80211_MESH_SETUP_USERSPACE_AMPE]);
+ if (setup->is_secure)
+ setup->user_mpm = true;

return 0;
}
--
1.7.10.4



2013-03-04 21:07:58

by Thomas Pedersen

[permalink] [raw]
Subject: [PATCH v2 3/5] mac80211: support userspace MPM

Earlier mac80211 would check whether some kind of mesh
security was enabled, when the real question was "is the
MPM in userspace"?

Signed-off-by: Thomas Pedersen <[email protected]>
---
net/mac80211/cfg.c | 3 ++-
net/mac80211/ieee80211_i.h | 1 +
net/mac80211/main.c | 3 ++-
net/mac80211/mesh.c | 2 +-
net/mac80211/mesh_plink.c | 9 +++++++--
net/mac80211/rx.c | 2 +-
6 files changed, 14 insertions(+), 6 deletions(-)

diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index b5f0a93..89c7b00 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1435,7 +1435,7 @@ static int ieee80211_change_station(struct wiphy *wiphy,

switch (sdata->vif.type) {
case NL80211_IFTYPE_MESH_POINT:
- if (sdata->u.mesh.security & IEEE80211_MESH_SEC_SECURED)
+ if (sdata->u.mesh.user_mpm)
statype = CFG80211_STA_MESH_PEER_USER;
else
statype = CFG80211_STA_MESH_PEER_KERNEL;
@@ -1729,6 +1729,7 @@ static int copy_mesh_setup(struct ieee80211_if_mesh *ifmsh,
ifmsh->mesh_sp_id = setup->sync_method;
ifmsh->mesh_pp_id = setup->path_sel_proto;
ifmsh->mesh_pm_id = setup->path_metric;
+ ifmsh->user_mpm = setup->user_mpm;
ifmsh->security = IEEE80211_MESH_SEC_NONE;
if (setup->is_authenticated)
ifmsh->security |= IEEE80211_MESH_SEC_AUTHED;
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 54d09ec..f4433f0 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -588,6 +588,7 @@ struct ieee80211_if_mesh {
IEEE80211_MESH_SEC_AUTHED = 0x1,
IEEE80211_MESH_SEC_SECURED = 0x2,
} security;
+ bool user_mpm;
/* Extensible Synchronization Framework */
const struct ieee80211_mesh_sync_ops *sync_ops;
s64 sync_offset_clockdrift_max;
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 120a553..c044bff 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -569,7 +569,8 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
wiphy->features |= NL80211_FEATURE_SK_TX_STATUS |
NL80211_FEATURE_SAE |
NL80211_FEATURE_HT_IBSS |
- NL80211_FEATURE_VIF_TXPOWER;
+ NL80211_FEATURE_VIF_TXPOWER |
+ NL80211_FEATURE_USERSPACE_MPM;

if (!ops->hw_scan)
wiphy->features |= NL80211_FEATURE_LOW_PRIORITY_SCAN |
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index f5d1afa..5ac017f 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -156,7 +156,7 @@ void mesh_sta_cleanup(struct sta_info *sta)
* an update.
*/
changed = mesh_accept_plinks_update(sdata);
- if (sdata->u.mesh.security == IEEE80211_MESH_SEC_NONE) {
+ if (!sdata->u.mesh.user_mpm) {
changed |= mesh_plink_deactivate(sta);
del_timer_sync(&sta->plink_timer);
}
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c
index 08df966..e259951 100644
--- a/net/mac80211/mesh_plink.c
+++ b/net/mac80211/mesh_plink.c
@@ -437,8 +437,9 @@ mesh_sta_info_alloc(struct ieee80211_sub_if_data *sdata, u8 *addr,
{
struct sta_info *sta = NULL;

- /* Userspace handles peer allocation when security is enabled */
- if (sdata->u.mesh.security & IEEE80211_MESH_SEC_AUTHED)
+ /* Userspace handles station allocation */
+ if (sdata->u.mesh.user_mpm ||
+ sdata->u.mesh.security & IEEE80211_MESH_SEC_AUTHED)
cfg80211_notify_new_peer_candidate(sdata->dev, addr,
elems->ie_start,
elems->total_len,
@@ -670,6 +671,10 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata,
if (len < IEEE80211_MIN_ACTION_SIZE + 3)
return;

+ if (sdata->u.mesh.user_mpm)
+ /* userspace must register for these */
+ return;
+
if (is_multicast_ether_addr(mgmt->da)) {
mpl_dbg(sdata,
"Mesh plink: ignore frame from multicast address\n");
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 1f940e2..5b4492a 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -2543,7 +2543,7 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
case WLAN_SP_MESH_PEERING_CONFIRM:
if (!ieee80211_vif_is_mesh(&sdata->vif))
goto invalid;
- if (sdata->u.mesh.security != IEEE80211_MESH_SEC_NONE)
+ if (sdata->u.mesh.user_mpm)
/* userspace handles this frame */
break;
goto queue;
--
1.7.10.4


2013-03-04 21:07:56

by Thomas Pedersen

[permalink] [raw]
Subject: [PATCH v2 2/5] cfg80211: rename mesh station types

The mesh station types used to refer to whether the
station was secure or nonsecure. Really the salient
information is whether it is managed by the kernel or
userspace

Signed-off-by: Thomas Pedersen <[email protected]>
---
include/net/cfg80211.h | 8 ++++----
net/mac80211/cfg.c | 4 ++--
net/wireless/nl80211.c | 8 ++++----
3 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index b6be55e..6a61237 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -690,8 +690,8 @@ struct station_parameters {
* supported/used)
* @CFG80211_STA_TDLS_PEER_ACTIVE: TDLS peer on managed interface (active
* entry that is operating, has been marked authorized by userspace)
- * @CFG80211_STA_MESH_PEER_NONSEC: peer on mesh interface (non-secured)
- * @CFG80211_STA_MESH_PEER_SECURE: peer on mesh interface (secured)
+ * @CFG80211_STA_MESH_PEER_KERNEL: peer on mesh interface (kernel managed)
+ * @CFG80211_STA_MESH_PEER_USER: peer on mesh interface (user managed)
*/
enum cfg80211_station_type {
CFG80211_STA_AP_CLIENT,
@@ -700,8 +700,8 @@ enum cfg80211_station_type {
CFG80211_STA_IBSS,
CFG80211_STA_TDLS_PEER_SETUP,
CFG80211_STA_TDLS_PEER_ACTIVE,
- CFG80211_STA_MESH_PEER_NONSEC,
- CFG80211_STA_MESH_PEER_SECURE,
+ CFG80211_STA_MESH_PEER_KERNEL,
+ CFG80211_STA_MESH_PEER_USER,
};

/**
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 8259a5b..b5f0a93 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1436,9 +1436,9 @@ static int ieee80211_change_station(struct wiphy *wiphy,
switch (sdata->vif.type) {
case NL80211_IFTYPE_MESH_POINT:
if (sdata->u.mesh.security & IEEE80211_MESH_SEC_SECURED)
- statype = CFG80211_STA_MESH_PEER_SECURE;
+ statype = CFG80211_STA_MESH_PEER_USER;
else
- statype = CFG80211_STA_MESH_PEER_NONSEC;
+ statype = CFG80211_STA_MESH_PEER_KERNEL;
break;
case NL80211_IFTYPE_ADHOC:
statype = CFG80211_STA_IBSS;
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 167fd83..eca897a 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -3595,8 +3595,8 @@ int cfg80211_check_station_change(struct wiphy *wiphy,
BUILD_BUG_ON(NL80211_STA_FLAG_MAX != 7);

switch (statype) {
- case CFG80211_STA_MESH_PEER_NONSEC:
- case CFG80211_STA_MESH_PEER_SECURE:
+ case CFG80211_STA_MESH_PEER_KERNEL:
+ case CFG80211_STA_MESH_PEER_USER:
/*
* No ignoring the TDLS flag here -- the userspace mesh
* code doesn't have the bug of including TDLS in the
@@ -3698,11 +3698,11 @@ int cfg80211_check_station_change(struct wiphy *wiphy,
case CFG80211_STA_TDLS_PEER_ACTIVE:
/* reject any changes */
return -EINVAL;
- case CFG80211_STA_MESH_PEER_NONSEC:
+ case CFG80211_STA_MESH_PEER_KERNEL:
if (params->sta_modify_mask & STATION_PARAM_APPLY_PLINK_STATE)
return -EINVAL;
break;
- case CFG80211_STA_MESH_PEER_SECURE:
+ case CFG80211_STA_MESH_PEER_USER:
if (params->plink_action != NL80211_PLINK_ACTION_NO_ACTION)
return -EINVAL;
break;
--
1.7.10.4


2013-03-04 21:08:00

by Thomas Pedersen

[permalink] [raw]
Subject: [PATCH v2 4/5] nl80211: user_mpm overrides auto_open_plinks

If the user requested a userspace MPM, automatically
disable auto_open_plinks to fully disable the kernel MPM.

Signed-off-by: Thomas Pedersen <[email protected]>
---
include/uapi/linux/nl80211.h | 6 ++++--
net/wireless/nl80211.c | 3 +++
2 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 8134c6a..79da871 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -2467,8 +2467,10 @@ enum nl80211_mesh_power_mode {
* @NL80211_MESHCONF_TTL: specifies the value of TTL field set at a source mesh
* point.
*
- * @NL80211_MESHCONF_AUTO_OPEN_PLINKS: whether we should automatically
- * open peer links when we detect compatible mesh peers.
+ * @NL80211_MESHCONF_AUTO_OPEN_PLINKS: whether we should automatically open
+ * peer links when we detect compatible mesh peers. Disabled if
+ * @NL80211_MESH_SETUP_USERSPACE_MPM or @NL80211_MESH_SETUP_USERSPACE_AMPE are
+ * set.
*
* @NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES: the number of action frames
* containing a PREQ that an MP can send to a particular destination (path
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index eca897a..ddd251b 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -7427,6 +7427,9 @@ static int nl80211_join_mesh(struct sk_buff *skb, struct genl_info *info)
return err;
}

+ if (setup.user_mpm)
+ cfg.auto_open_plinks = false;
+
if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) {
err = nl80211_parse_chandef(rdev, info, &setup.chandef);
if (err)
--
1.7.10.4


2013-03-04 21:08:02

by Thomas Pedersen

[permalink] [raw]
Subject: [PATCH v2 5/5] mac80211: disallow changing auto_open_plinks

while user MPM is running.

Signed-off-by: Thomas Pedersen <[email protected]>
---
net/mac80211/cfg.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 89c7b00..ebfb060 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1773,8 +1773,11 @@ static int ieee80211_update_mesh_config(struct wiphy *wiphy,
conf->dot11MeshTTL = nconf->dot11MeshTTL;
if (_chg_mesh_attr(NL80211_MESHCONF_ELEMENT_TTL, mask))
conf->element_ttl = nconf->element_ttl;
- if (_chg_mesh_attr(NL80211_MESHCONF_AUTO_OPEN_PLINKS, mask))
+ if (_chg_mesh_attr(NL80211_MESHCONF_AUTO_OPEN_PLINKS, mask)) {
+ if (ifmsh->user_mpm)
+ return -EBUSY;
conf->auto_open_plinks = nconf->auto_open_plinks;
+ }
if (_chg_mesh_attr(NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR, mask))
conf->dot11MeshNbrOffsetMaxNeighbor =
nconf->dot11MeshNbrOffsetMaxNeighbor;
--
1.7.10.4


2013-03-05 18:58:08

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH v2 1/5] nl80211: explicit userspace MPM

On Mon, 2013-03-04 at 13:06 -0800, Thomas Pedersen wrote:
> Secure mesh had the implicit requirement that the Mesh
> Peering Management entity be in userspace. However
> userspace might want to implement an open MPM as well, so
> specify a mesh setup parameter to indicate this.

Applied all.

johannes