2008-02-04 21:23:44

by Luis Carlos Cobo

[permalink] [raw]
Subject: [PATCH 02/13] o11s: (nl80211/cfg80211) support for mesh interfaces and set_mesh_cfg command

This command allows setting the mesh ID for a (pre) 802.11s mesh interface. If
this command is not used, mesh interfaces will use the wildcard, zero-length
mesh ID.

Signed-off-by: Luis Carlos Cobo <[email protected]>
---
include/linux/nl80211.h | 8 ++++++++
include/net/cfg80211.h | 13 +++++++++++++
net/mac80211/cfg.c | 28 ++++++++++++++++++++++++++++
net/wireless/nl80211.c | 43 +++++++++++++++++++++++++++++++++++++++++++
4 files changed, 92 insertions(+), 0 deletions(-)

diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index 6369506..71c6125 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -48,6 +48,7 @@
* %NL80211_ATTR_IFINDEX and %NL80211_ATTR_WIPHY. Can also be sent from
* userspace to request deletion of a virtual interface, then requires
* attribute %NL80211_ATTR_IFINDEX.
+ * @NL80211_CMD_SET_MESH_CFG: start mesh operation
*
* @NL80211_CMD_GET_KEY: Get sequence counter information for a key specified
* by %NL80211_ATTR_KEY_IDX and/or %NL80211_ATTR_MAC.
@@ -112,6 +113,8 @@ enum nl80211_commands {

/* add commands here */

+ NL80211_CMD_SET_MESH_CFG,
+
/* used to define NL80211_CMD_MAX below */
__NL80211_CMD_AFTER_LAST,
NL80211_CMD_MAX = __NL80211_CMD_AFTER_LAST - 1
@@ -163,6 +166,7 @@ enum nl80211_commands {
*
* @NL80211_ATTR_WIPHY_BANDS: Information about an operating bands,
* consisting of a nested array.
+ * @NL80211_ATTR_MESH_ID: mesh id (1-32 bytes)
*
* @NL80211_ATTR_MAX: highest attribute number currently defined
* @__NL80211_ATTR_AFTER_LAST: internal use
@@ -202,6 +206,8 @@ enum nl80211_attrs {

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

+ NL80211_ATTR_MESH_ID,
+
__NL80211_ATTR_AFTER_LAST,
NL80211_ATTR_MAX = __NL80211_ATTR_AFTER_LAST - 1
};
@@ -218,6 +224,7 @@ enum nl80211_attrs {
* @NL80211_IFTYPE_AP_VLAN: VLAN interface for access points
* @NL80211_IFTYPE_WDS: wireless distribution interface
* @NL80211_IFTYPE_MONITOR: monitor interface receiving all frames
+ * @NL80211_IFTYPE_MESH_POINT: mesh point
* @NL80211_IFTYPE_MAX: highest interface type number currently defined
* @__NL80211_IFTYPE_AFTER_LAST: internal use
*
@@ -233,6 +240,7 @@ enum nl80211_iftype {
NL80211_IFTYPE_AP_VLAN,
NL80211_IFTYPE_WDS,
NL80211_IFTYPE_MONITOR,
+ NL80211_IFTYPE_MESH_POINT,

/* keep last */
__NL80211_IFTYPE_AFTER_LAST,
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index bcc480b..b09e258 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -12,6 +12,16 @@
* Copyright 2006, 2007 Johannes Berg <[email protected]>
*/

+/*
+ * struct mesh_params - describes mesh parameters
+ * @mesh_id: mesh ID to use
+ * @mesh_id_len: length of the mesh ID
+ */
+struct mesh_params {
+ u8 *mesh_id;
+ int mesh_id_len;
+};
+
/* Radiotap header iteration
* implemented in net/wireless/radiotap.c
* docs in Documentation/networking/radiotap-headers.txt
@@ -187,6 +197,7 @@ struct wiphy;
*
* @add_key: add a key with the given parameters. @mac_addr will be %NULL
* when adding a group key.
+ * @set_mesh_cfg: set mesh parameters (by now, just mesh id)
*
* @get_key: get information about the key with the given parameters.
* @mac_addr will be %NULL when requesting information for a group
@@ -245,6 +256,8 @@ struct cfg80211_ops {
u8 *mac, struct station_parameters *params);
int (*get_station)(struct wiphy *wiphy, struct net_device *dev,
u8 *mac, struct station_stats *stats);
+ int (*set_mesh_cfg)(struct wiphy *wiphy, struct net_device *dev,
+ struct mesh_params *params);
};

#endif /* __NET_CFG80211_H */
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 15b8cf9..416ce05 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -28,6 +28,8 @@ nl80211_type_to_mac80211_type(enum nl80211_iftype type)
return IEEE80211_IF_TYPE_STA;
case NL80211_IFTYPE_MONITOR:
return IEEE80211_IF_TYPE_MNTR;
+ case NL80211_IFTYPE_MESH_POINT:
+ return IEEE80211_IF_TYPE_MESH_POINT;
default:
return IEEE80211_IF_TYPE_INVALID;
}
@@ -637,6 +639,31 @@ static int ieee80211_change_station(struct wiphy *wiphy,
return 0;
}

+static int ieee80211_if_set_mesh_cfg(struct wiphy *wiphy,
+ struct net_device *dev, struct mesh_params *params)
+{
+ struct ieee80211_local *local = wiphy_priv(wiphy);
+ struct ieee80211_if_sta *ifsta;
+ struct ieee80211_sub_if_data *sdata = NULL;
+ if (unlikely(local->reg_state != IEEE80211_DEV_REGISTERED))
+ return -ENODEV;
+
+ sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+ if (sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT)
+ return -EINVAL;
+
+ ifsta = &sdata->u.sta;
+ ifsta->mesh_id_len = params->mesh_id_len;
+ if (params->mesh_id_len)
+ memcpy(ifsta->mesh_id, params->mesh_id, params->mesh_id_len);
+
+ /* If the iface is down, it will be configure when it is opened */
+ if (netif_running(dev))
+ ieee80211_if_config(dev);
+ return 0;
+}
+
+
struct cfg80211_ops mac80211_config_ops = {
.add_virtual_intf = ieee80211_add_iface,
.del_virtual_intf = ieee80211_del_iface,
@@ -652,4 +679,5 @@ struct cfg80211_ops mac80211_config_ops = {
.del_station = ieee80211_del_station,
.change_station = ieee80211_change_station,
.get_station = ieee80211_get_station,
+ .set_mesh_cfg = ieee80211_if_set_mesh_cfg,
};
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index b123f58..d332683 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -82,6 +82,8 @@ static struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] __read_mostly = {
[NL80211_ATTR_STA_SUPPORTED_RATES] = { .type = NLA_BINARY,
.len = NL80211_MAX_SUPP_RATES },
[NL80211_ATTR_STA_VLAN] = { .type = NLA_U32 },
+ [NL80211_ATTR_MESH_ID] = { .type = NLA_NUL_STRING,
+ .len = IEEE80211_MAX_MESH_ID_LEN },
};

/* message building helper */
@@ -1079,6 +1081,41 @@ static int nl80211_del_station(struct sk_buff *skb, struct genl_info *info)
return err;
}

+static int nl80211_set_mesh_cfg(struct sk_buff *skb, struct genl_info *info)
+{
+ struct cfg80211_registered_device *drv;
+ int err;
+ struct net_device *dev;
+ struct mesh_params params;
+
+ memset(&params, 0, sizeof(params));
+
+ err = get_drv_dev_by_info_ifindex(info, &drv, &dev);
+ if (err)
+ return err;
+
+ if (!drv->ops->set_mesh_cfg) {
+ err = -EOPNOTSUPP;
+ goto out;
+ }
+
+ if (!info->attrs[NL80211_ATTR_MESH_ID])
+ return -EINVAL;
+
+ params.mesh_id = nla_data(info->attrs[NL80211_ATTR_MESH_ID]);
+ /* Cut null character */
+ params.mesh_id_len = nla_len(info->attrs[NL80211_ATTR_MESH_ID]) - 1 ;
+
+ rtnl_lock();
+ err = drv->ops->set_mesh_cfg(&drv->wiphy, dev, &params);
+ rtnl_unlock();
+
+ out:
+ cfg80211_put_dev(drv);
+ dev_put(dev);
+ return err;
+}
+
static struct genl_ops nl80211_ops[] = {
{
.cmd = NL80211_CMD_GET_WIPHY,
@@ -1185,6 +1222,12 @@ static struct genl_ops nl80211_ops[] = {
.policy = nl80211_policy,
.flags = GENL_ADMIN_PERM,
},
+ {
+ .cmd = NL80211_CMD_SET_MESH_CFG,
+ .doit = nl80211_set_mesh_cfg,
+ .policy = nl80211_policy,
+ .flags = GENL_ADMIN_PERM,
+ },
};

/* multicast groups */
--
1.5.2.5





2008-02-09 00:24:39

by Luis Carlos Cobo

[permalink] [raw]
Subject: Re: [PATCH 02/13] o11s: (nl80211/cfg80211) support for mesh interfaces and set_mesh_cfg command

On Thu, 2008-02-07 at 01:18 +0100, Johannes Berg wrote:
> However, maybe I don't understand the mesh ID well enough yet, can you
> maybe explain in a few sentences where it is used and what for?

The mesh ID works as the SSID for mesh networks, on mesh beacons/probes
SSID is set to the wildcard value to avoid interfering with non-mesh
STAs.

An MP only opens a peer link with a neighboring mesh peer if you have
the same mesh configuration. This mesh configuration is composed by the
mesh ID and path discovery protocol/metric/congestion control IDs. Once
the link is open the mesh ID is not included in the frames. Let me know
if you want more info.

It might be a good idea as you suggest in another thread to refuse to
change the mesh id for running interfaces as it would make a lot of
information stale, will consider it.

--
Luis Carlos Cobo Rus GnuPG ID: 44019B60
cozybit Inc.



2008-02-07 10:35:40

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH 02/13] o11s: (nl80211/cfg80211) support for mesh interfaces and set_mesh_cfg command


> +/*
> + * struct mesh_params - describes mesh parameters

Here, and various other places too, you need "/**" rather than just "/*"
for kernel-doc to be able to pick it up.

> * @add_key: add a key with the given parameters. @mac_addr will be %NULL
> * when adding a group key.
> + * @set_mesh_cfg: set mesh parameters (by now, just mesh id)
> *
> * @get_key: get information about the key with the given parameters.
> * @mac_addr will be %NULL when requesting information for a group

Please keep the key operations grouped.

> @@ -82,6 +82,8 @@ static struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] __read_mostly = {
> [NL80211_ATTR_STA_SUPPORTED_RATES] = { .type = NLA_BINARY,
> .len = NL80211_MAX_SUPP_RATES },
> [NL80211_ATTR_STA_VLAN] = { .type = NLA_U32 },
> + [NL80211_ATTR_MESH_ID] = { .type = NLA_NUL_STRING,
> + .len = IEEE80211_MAX_MESH_ID_LEN },

That should be NLA_BINARY since it's not a NULL-terminated string but
rather an arbitrary up-to-MESH_ID_LEN-long byte value, no?

> + params.mesh_id = nla_data(info->attrs[NL80211_ATTR_MESH_ID]);
> + /* Cut null character */
> + params.mesh_id_len = nla_len(info->attrs[NL80211_ATTR_MESH_ID]) - 1 ;

Then you can save that -1 and the comment :)

FWIW, I'm not entirely happy with this interface. I tried to keep
ADD/DEL/GET/SET groups of commands to create/delete/get/set
object/object properties. This breaks that, but I guess it's just a
single value that is set. That's why I initially suggested to make it
part of the SET_INTERFACE command since it seems to me that this
identifies the mesh you'll be using.

However, maybe I don't understand the mesh ID well enough yet, can you
maybe explain in a few sentences where it is used and what for?

johannes


Attachments:
signature.asc (828.00 B)
This is a digitally signed message part

2008-02-13 12:08:14

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH 02/13] o11s: (nl80211/cfg80211) support for mesh interfaces and set_mesh_cfg command

Somehow I kept this around, sorry...

> The mesh ID works as the SSID for mesh networks, on mesh beacons/probes
> SSID is set to the wildcard value to avoid interfering with non-mesh
> STAs.

Right. So it's just the mesh identifier.

> An MP only opens a peer link with a neighboring mesh peer if you have
> the same mesh configuration. This mesh configuration is composed by the
> mesh ID and path discovery protocol/metric/congestion control IDs. Once
> the link is open the mesh ID is not included in the frames. Let me know
> if you want more info.

We don't have settings for the other control IDs yet, or did I miss
them?

> It might be a good idea as you suggest in another thread to refuse to
> change the mesh id for running interfaces as it would make a lot of
> information stale, will consider it.

Ok. I think this is quite a difference to the SSID where you can roam
between networks, but I guess that roaming between different mesh
networks doesn't really make sense since the point is to be part of the
mesh...

I still think the mesh parameters could be per-interface attributes
rather than require a new command, but I'm not too fixed on the idea
either (although currently it breaks the get/set/new/del grouping.

Another, off-topic in this thread, question: How is beaconing defined
for a mesh point? Is it similar to how it works in an IBSS?

johannes


Attachments:
signature.asc (828.00 B)
This is a digitally signed message part

2008-02-13 18:48:45

by Luis Carlos Cobo

[permalink] [raw]
Subject: Re: [PATCH 02/13] o11s: (nl80211/cfg80211) support for mesh interfaces and set_mesh_cfg command

On Wed, 2008-02-13 at 08:51 +0100, Johannes Berg wrote:
> > the same mesh configuration. This mesh configuration is composed by the
> > mesh ID and path discovery protocol/metric/congestion control IDs. Once
> > the link is open the mesh ID is not included in the frames. Let me know
> > if you want more info.
>
> We don't have settings for the other control IDs yet, or did I miss
> them?

Those settings are in the struct ieee80211_if_sta. We are just
hardcoding the values on route initialization, since we just support one
path protocol and link metric.

> Another, off-topic in this thread, question: How is beaconing defined
> for a mesh point? Is it similar to how it works in an IBSS?

According to the draft you can choose IBSS-like beaconing (wait a small
random time before sending the beacon and don't send it if you hear it
first) or AP-like beaconing.

--
Luis Carlos Cobo Rus GnuPG ID: 44019B60
cozybit Inc.