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
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
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
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
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
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