Search Linux Wireless

Re: [RFC 5/5 v2] cfg80211/mac80211: add mesh join/leave commands

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Johannes,

Looks good from this end, including the new iw commands.  The only
issue that we observed is that now that we can leave and join a new
mesh, we need to do some more state cleanup on stop_mesh.  Otherwise
we could move to a new mesh and still talk to the previous peers.  I
think this would be sufficient:

diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 107a0cb..b1242b6 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -246,7 +246,6 @@ void ieee80211_bss_info_change_notify(struct
ieee80211_sub_if_data *sdata,
                                        !!sdata->u.ibss.presp;
                                break;
                        case NL80211_IFTYPE_MESH_POINT:
-                               sdata->vif.bss_conf.enable_beacon = true;
                                break;
                        default:
                                /* not reached */
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index d814fab..cc458dd 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -522,6 +522,7 @@ void ieee80211_start_mesh(struct
ieee80211_sub_if_data *sdata)
        ieee80211_mesh_root_setup(ifmsh);
        ieee80211_queue_work(&local->hw, &sdata->work);
        sdata->vif.bss_conf.beacon_int = MESH_DEFAULT_BEACON_INTERVAL;
+       sdata->vif.bss_conf.enable_beacon = true;
        ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON |
                                                BSS_CHANGED_BEACON_ENABLED |
                                                BSS_CHANGED_BEACON_INT);
@@ -530,6 +531,13 @@ void ieee80211_start_mesh(struct
ieee80211_sub_if_data *sdata)
 void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata)
 {
        struct ieee80211_local *local = sdata->local;
+       struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
+
+       ifmsh->mesh_id_len = 0;
+       memset(ifmsh->mesh_id, 0, IEEE80211_MAX_MESH_ID_LEN);
+       sdata->vif.bss_conf.enable_beacon = false;
+       ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED);
+       sta_info_flush(local, NULL);

        del_timer_sync(&sdata->u.mesh.housekeeping_timer);
        del_timer_sync(&sdata->u.mesh.mesh_path_root_timer);

Cheers,

Javier

On Thu, Dec 2, 2010 at 12:45 AM, Johannes Berg
<johannes@xxxxxxxxxxxxxxxx> wrote:
> From: Johannes Berg <johannes.berg@xxxxxxxxx>
>
> Instead of tying mesh activity to interface up,
> add join and leave commands for mesh. Since we
> must be backward compatible, let cfg80211 handle
> joining a mesh if a mesh ID was pre-configured
> when the device goes up.
>
> Note that this therefore must modify mac80211 as
> well since mac80211 needs to lose the logic to
> start the mesh on interface up.
>
> We now allow querying mesh parameters before the
> mesh is connected, which simply returns defaults.
> Setting them (internally renamed to "update") is
> only allowed while connected. Specify them with
> the new mesh join command instead where needed.
>
> Signed-off-by: Johannes Berg <johannes.berg@xxxxxxxxx>
> ---
> v2: - fix join on netdev up (pointed out by Javier)
>    - only require mesh ID (pointed out by Javier)
>    - more sanity checking around get/set_mesh_params
>    - rename set_mesh_params to update_mesh_params,
>      disallow calling it before connected to mesh
>    - add some mesh interface type checks
>    - introduce mesh_setup struct for static config
>
> I have lightly tested this. You can find a new
> test branch of iw that includes support for the
> new commands here:
>
> http://git.sipsolutions.net/?p=iw.git;a=shortlog;h=refs/heads/mesh
>
>
> I think this is about ready, maybe with some
> minor issues still. I'd appreciate if you could
> review and test it, and then we can add the IE
> and path selection protocols to the mesh_setup
> struct and the iw mesh join command.
>
>
>  include/linux/nl80211.h    |    8 ++
>  include/net/cfg80211.h     |   38 +++++++++---
>  net/mac80211/cfg.c         |   39 +++++++++---
>  net/mac80211/ieee80211_i.h |   13 ----
>  net/mac80211/iface.c       |   14 ----
>  net/mac80211/mesh.c        |   20 ------
>  net/mac80211/mesh.h        |   23 -------
>  net/wireless/Makefile      |    2
>  net/wireless/core.c        |   15 ++++
>  net/wireless/core.h        |   13 ++++
>  net/wireless/mesh.c        |  134 ++++++++++++++++++++++++++++++++++++++++++++
>  net/wireless/nl80211.c     |  137 ++++++++++++++++++++++++++++++++++++++-------
>  net/wireless/util.c        |    1
>  13 files changed, 346 insertions(+), 111 deletions(-)
>
> --- wireless-testing.orig/include/linux/nl80211.h       2010-12-02 09:32:13.000000000 +0100
> +++ wireless-testing/include/linux/nl80211.h    2010-12-02 09:38:22.000000000 +0100
> @@ -394,6 +394,11 @@
>  *
>  * @NL80211_CMD_SET_WDS_PEER: Set the MAC address of the peer on a WDS interface.
>  *
> + * @NL80211_CMD_JOIN_MESH: Join a mesh. The mesh ID must be given, and initial
> + *     mesh config parameters may be given.
> + * @NL80211_CMD_LEAVE_MESH: Leave the mesh network -- no special arguments, the
> + *     network is determined by the network interface.
> + *
>  * @NL80211_CMD_MAX: highest used command number
>  * @__NL80211_CMD_AFTER_LAST: internal use
>  */
> @@ -500,6 +505,9 @@ enum nl80211_commands {
>
>        NL80211_CMD_FRAME_WAIT_CANCEL,
>
> +       NL80211_CMD_JOIN_MESH,
> +       NL80211_CMD_LEAVE_MESH,
> +
>        /* add new commands above here */
>
>        /* used to define NL80211_CMD_MAX below */
> --- wireless-testing.orig/include/net/cfg80211.h        2010-12-02 09:32:13.000000000 +0100
> +++ wireless-testing/include/net/cfg80211.h     2010-12-02 09:38:22.000000000 +0100
> @@ -258,13 +258,9 @@ struct ieee80211_supported_band {
>
>  /**
>  * struct vif_params - describes virtual interface parameters
> - * @mesh_id: mesh ID to use
> - * @mesh_id_len: length of the mesh ID
>  * @use_4addr: use 4-address frames
>  */
>  struct vif_params {
> -       u8 *mesh_id;
> -       int mesh_id_len;
>        int use_4addr;
>  };
>
> @@ -615,6 +611,11 @@ struct bss_parameters {
>        int ap_isolate;
>  };
>
> +/*
> + * struct mesh_config - 802.11s mesh configuration
> + *
> + * These parameters can be changed while the mesh is active.
> + */
>  struct mesh_config {
>        /* Timeouts in ms */
>        /* Mesh plink management parameters */
> @@ -636,6 +637,18 @@ struct mesh_config {
>  };
>
>  /**
> + * struct mesh_setup - 802.11s mesh setup configuration
> + * @mesh_id: the mesh ID
> + * @mesh_id_len: length of the mesh ID, at least 1 and at most 32 bytes
> + *
> + * These parameters are fixed when the mesh is created.
> + */
> +struct mesh_setup {
> +       const u8 *mesh_id;
> +       u8 mesh_id_len;
> +};
> +
> +/**
>  * struct ieee80211_txq_params - TX queue parameters
>  * @queue: TX queue identifier (NL80211_TXQ_Q_*)
>  * @txop: Maximum burst time in units of 32 usecs, 0 meaning disabled
> @@ -1076,7 +1089,7 @@ struct cfg80211_pmksa {
>  *
>  * @get_mesh_params: Put the current mesh parameters into *params
>  *
> - * @set_mesh_params: Set mesh parameters.
> + * @update_mesh_params: Update mesh parameters on a running mesh.
>  *     The mask is a bitfield which tells us which parameters to
>  *     set, and which to leave alone.
>  *
> @@ -1220,9 +1233,14 @@ struct cfg80211_ops {
>        int     (*get_mesh_params)(struct wiphy *wiphy,
>                                struct net_device *dev,
>                                struct mesh_config *conf);
> -       int     (*set_mesh_params)(struct wiphy *wiphy,
> -                               struct net_device *dev,
> -                               const struct mesh_config *nconf, u32 mask);
> +       int     (*update_mesh_params)(struct wiphy *wiphy,
> +                                     struct net_device *dev, u32 mask,
> +                                     const struct mesh_config *nconf);
> +       int     (*join_mesh)(struct wiphy *wiphy, struct net_device *dev,
> +                            const struct mesh_config *conf,
> +                            const struct mesh_setup *setup);
> +       int     (*leave_mesh)(struct wiphy *wiphy, struct net_device *dev);
> +
>        int     (*change_bss)(struct wiphy *wiphy, struct net_device *dev,
>                              struct bss_parameters *params);
>
> @@ -1638,6 +1656,8 @@ struct cfg80211_cached_keys;
>  * @bssid: (private) Used by the internal configuration code
>  * @ssid: (private) Used by the internal configuration code
>  * @ssid_len: (private) Used by the internal configuration code
> + * @mesh_id_len: (private) Used by the internal configuration code
> + * @mesh_id_up_len: (private) Used by the internal configuration code
>  * @wext: (private) Used by the internal wireless extensions compat code
>  * @use_4addr: indicates 4addr mode is used on this interface, must be
>  *     set by driver (if supported) on add_interface BEFORE registering the
> @@ -1667,7 +1687,7 @@ struct wireless_dev {
>
>        /* currently used for IBSS and SME - might be rearranged later */
>        u8 ssid[IEEE80211_MAX_SSID_LEN];
> -       u8 ssid_len;
> +       u8 ssid_len, mesh_id_len, mesh_id_up_len;
>        enum {
>                CFG80211_SME_IDLE,
>                CFG80211_SME_CONNECTING,
> --- wireless-testing.orig/net/wireless/Makefile 2010-12-02 09:32:13.000000000 +0100
> +++ wireless-testing/net/wireless/Makefile      2010-12-02 09:38:22.000000000 +0100
> @@ -10,7 +10,7 @@ obj-$(CONFIG_WEXT_SPY) += wext-spy.o
>  obj-$(CONFIG_WEXT_PRIV) += wext-priv.o
>
>  cfg80211-y += core.o sysfs.o radiotap.o util.o reg.o scan.o nl80211.o
> -cfg80211-y += mlme.o ibss.o sme.o chan.o ethtool.o
> +cfg80211-y += mlme.o ibss.o sme.o chan.o ethtool.o mesh.o
>  cfg80211-$(CONFIG_CFG80211_DEBUGFS) += debugfs.o
>  cfg80211-$(CONFIG_CFG80211_WEXT) += wext-compat.o wext-sme.o
>  cfg80211-$(CONFIG_CFG80211_INTERNAL_REGDB) += regdb.o
> --- wireless-testing.orig/net/wireless/core.h   2010-12-02 09:32:13.000000000 +0100
> +++ wireless-testing/net/wireless/core.h        2010-12-02 09:38:22.000000000 +0100
> @@ -285,6 +285,19 @@ void __cfg80211_ibss_joined(struct net_d
>  int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev,
>                            struct wireless_dev *wdev);
>
> +/* mesh */
> +extern const struct mesh_config default_mesh_config;
> +int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev,
> +                        struct net_device *dev,
> +                        const u8 *mesh_id, u8 mesh_id_len,
> +                        const struct mesh_config *conf);
> +int cfg80211_join_mesh(struct cfg80211_registered_device *rdev,
> +                      struct net_device *dev,
> +                      const u8 *mesh_id, u8 mesh_id_len,
> +                      const struct mesh_config *conf);
> +int cfg80211_leave_mesh(struct cfg80211_registered_device *rdev,
> +                       struct net_device *dev);
> +
>  /* MLME */
>  int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
>                         struct net_device *dev,
> --- /dev/null   1970-01-01 00:00:00.000000000 +0000
> +++ wireless-testing/net/wireless/mesh.c        2010-12-02 09:38:22.000000000 +0100
> @@ -0,0 +1,134 @@
> +#include <linux/ieee80211.h>
> +#include <net/cfg80211.h>
> +#include "core.h"
> +
> +/* Default values, timeouts in ms */
> +#define MESH_TTL               31
> +#define MESH_MAX_RETR          3
> +#define MESH_RET_T             100
> +#define MESH_CONF_T            100
> +#define MESH_HOLD_T            100
> +
> +#define MESH_PATH_TIMEOUT      5000
> +/* Minimum interval between two consecutive PREQs originated by the same
> + * interface
> + */
> +#define MESH_PREQ_MIN_INT      10
> +#define MESH_DIAM_TRAVERSAL_TIME 50
> +/* A path will be refreshed if it is used PATH_REFRESH_TIME milliseconds before
> + * timing out.  This way it will remain ACTIVE and no data frames will be
> + * unnecesarily held in the pending queue.
> + */
> +#define MESH_PATH_REFRESH_TIME                 1000
> +#define MESH_MIN_DISCOVERY_TIMEOUT (2 * MESH_DIAM_TRAVERSAL_TIME)
> +
> +/* Default maximum number of established plinks per interface */
> +#define MESH_MAX_ESTAB_PLINKS  32
> +
> +#define MESH_MAX_PREQ_RETRIES 4
> +
> +
> +const struct mesh_config default_mesh_config = {
> +       .dot11MeshRetryTimeout = MESH_RET_T,
> +       .dot11MeshConfirmTimeout = MESH_CONF_T,
> +       .dot11MeshHoldingTimeout = MESH_HOLD_T,
> +       .dot11MeshMaxRetries = MESH_MAX_RETR,
> +       .dot11MeshTTL = MESH_TTL,
> +       .auto_open_plinks = true,
> +       .dot11MeshMaxPeerLinks = MESH_MAX_ESTAB_PLINKS,
> +       .dot11MeshHWMPactivePathTimeout = MESH_PATH_TIMEOUT,
> +       .dot11MeshHWMPpreqMinInterval = MESH_PREQ_MIN_INT,
> +       .dot11MeshHWMPnetDiameterTraversalTime = MESH_DIAM_TRAVERSAL_TIME,
> +       .dot11MeshHWMPmaxPREQretries = MESH_MAX_PREQ_RETRIES,
> +       .path_refresh_time = MESH_PATH_REFRESH_TIME,
> +       .min_discovery_timeout = MESH_MIN_DISCOVERY_TIMEOUT,
> +};
> +
> +
> +int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev,
> +                        struct net_device *dev,
> +                        const u8 *mesh_id, u8 mesh_id_len,
> +                        const struct mesh_config *conf)
> +{
> +       struct wireless_dev *wdev = dev->ieee80211_ptr;
> +       struct mesh_setup setup = {
> +               .mesh_id = mesh_id,
> +               .mesh_id_len = mesh_id_len,
> +       };
> +       int err;
> +
> +       BUILD_BUG_ON(IEEE80211_MAX_SSID_LEN != IEEE80211_MAX_MESH_ID_LEN);
> +
> +       ASSERT_WDEV_LOCK(wdev);
> +
> +       if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT)
> +               return -EOPNOTSUPP;
> +
> +       if (wdev->mesh_id_len)
> +               return -EALREADY;
> +
> +       if (!mesh_id_len)
> +               return -EINVAL;
> +
> +       if (!rdev->ops->join_mesh)
> +               return -EOPNOTSUPP;
> +
> +       err = rdev->ops->join_mesh(&rdev->wiphy, dev, conf, &setup);
> +       if (!err) {
> +               memcpy(wdev->ssid, mesh_id, mesh_id_len);
> +               wdev->mesh_id_len = mesh_id_len;
> +       }
> +
> +       return err;
> +}
> +
> +int cfg80211_join_mesh(struct cfg80211_registered_device *rdev,
> +                      struct net_device *dev,
> +                      const u8 *mesh_id, u8 mesh_id_len,
> +                      const struct mesh_config *conf)
> +{
> +       struct wireless_dev *wdev = dev->ieee80211_ptr;
> +       int err;
> +
> +       wdev_lock(wdev);
> +       err = __cfg80211_join_mesh(rdev, dev, mesh_id, mesh_id_len, conf);
> +       wdev_unlock(wdev);
> +
> +       return err;
> +}
> +
> +static int __cfg80211_leave_mesh(struct cfg80211_registered_device *rdev,
> +                                struct net_device *dev)
> +{
> +       struct wireless_dev *wdev = dev->ieee80211_ptr;
> +       int err;
> +
> +       ASSERT_WDEV_LOCK(wdev);
> +
> +       if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT)
> +               return -EOPNOTSUPP;
> +
> +       if (!rdev->ops->leave_mesh)
> +               return -EOPNOTSUPP;
> +
> +       if (!wdev->mesh_id_len)
> +               return -ENOTCONN;
> +
> +       err = rdev->ops->leave_mesh(&rdev->wiphy, dev);
> +       if (!err)
> +               wdev->mesh_id_len = 0;
> +       return err;
> +}
> +
> +int cfg80211_leave_mesh(struct cfg80211_registered_device *rdev,
> +                       struct net_device *dev)
> +{
> +       struct wireless_dev *wdev = dev->ieee80211_ptr;
> +       int err;
> +
> +       wdev_lock(wdev);
> +       err = __cfg80211_leave_mesh(rdev, dev);
> +       wdev_unlock(wdev);
> +
> +       return err;
> +}
> --- wireless-testing.orig/net/wireless/nl80211.c        2010-12-02 09:38:20.000000000 +0100
> +++ wireless-testing/net/wireless/nl80211.c     2010-12-02 09:38:31.000000000 +0100
> @@ -661,13 +661,14 @@ static int nl80211_send_wiphy(struct sk_
>        CMD(add_beacon, NEW_BEACON);
>        CMD(add_station, NEW_STATION);
>        CMD(add_mpath, NEW_MPATH);
> -       CMD(set_mesh_params, SET_MESH_PARAMS);
> +       CMD(update_mesh_params, SET_MESH_PARAMS);
>        CMD(change_bss, SET_BSS);
>        CMD(auth, AUTHENTICATE);
>        CMD(assoc, ASSOCIATE);
>        CMD(deauth, DEAUTHENTICATE);
>        CMD(disassoc, DISASSOCIATE);
>        CMD(join_ibss, JOIN_IBSS);
> +       CMD(join_mesh, JOIN_MESH);
>        CMD(set_pmksa, SET_PMKSA);
>        CMD(del_pmksa, DEL_PMKSA);
>        CMD(flush_pmksa, FLUSH_PMKSA);
> @@ -1324,11 +1325,21 @@ static int nl80211_set_interface(struct
>        }
>
>        if (info->attrs[NL80211_ATTR_MESH_ID]) {
> +               struct wireless_dev *wdev = dev->ieee80211_ptr;
> +
>                if (ntype != NL80211_IFTYPE_MESH_POINT)
>                        return -EINVAL;
> -               params.mesh_id = nla_data(info->attrs[NL80211_ATTR_MESH_ID]);
> -               params.mesh_id_len = nla_len(info->attrs[NL80211_ATTR_MESH_ID]);
> -               change = true;
> +               if (netif_running(dev))
> +                       return -EBUSY;
> +
> +               wdev_lock(wdev);
> +               BUILD_BUG_ON(IEEE80211_MAX_SSID_LEN !=
> +                            IEEE80211_MAX_MESH_ID_LEN);
> +               wdev->mesh_id_up_len =
> +                       nla_len(info->attrs[NL80211_ATTR_MESH_ID]);
> +               memcpy(wdev->ssid, nla_data(info->attrs[NL80211_ATTR_MESH_ID]),
> +                      wdev->mesh_id_up_len);
> +               wdev_unlock(wdev);
>        }
>
>        if (info->attrs[NL80211_ATTR_4ADDR]) {
> @@ -1388,12 +1399,6 @@ static int nl80211_new_interface(struct
>            !(rdev->wiphy.interface_modes & (1 << type)))
>                return -EOPNOTSUPP;
>
> -       if (type == NL80211_IFTYPE_MESH_POINT &&
> -           info->attrs[NL80211_ATTR_MESH_ID]) {
> -               params.mesh_id = nla_data(info->attrs[NL80211_ATTR_MESH_ID]);
> -               params.mesh_id_len = nla_len(info->attrs[NL80211_ATTR_MESH_ID]);
> -       }
> -
>        if (info->attrs[NL80211_ATTR_4ADDR]) {
>                params.use_4addr = !!nla_get_u8(info->attrs[NL80211_ATTR_4ADDR]);
>                err = nl80211_valid_4addr(rdev, NULL, params.use_4addr, type);
> @@ -1410,6 +1415,20 @@ static int nl80211_new_interface(struct
>        if (IS_ERR(dev))
>                return PTR_ERR(dev);
>
> +       if (type == NL80211_IFTYPE_MESH_POINT &&
> +           info->attrs[NL80211_ATTR_MESH_ID]) {
> +               struct wireless_dev *wdev = dev->ieee80211_ptr;
> +
> +               wdev_lock(wdev);
> +               BUILD_BUG_ON(IEEE80211_MAX_SSID_LEN !=
> +                            IEEE80211_MAX_MESH_ID_LEN);
> +               wdev->mesh_id_up_len =
> +                       nla_len(info->attrs[NL80211_ATTR_MESH_ID]);
> +               memcpy(wdev->ssid, nla_data(info->attrs[NL80211_ATTR_MESH_ID]),
> +                      wdev->mesh_id_up_len);
> +               wdev_unlock(wdev);
> +       }
> +
>        return 0;
>  }
>
> @@ -2543,21 +2562,32 @@ static int nl80211_req_set_reg(struct sk
>  }
>
>  static int nl80211_get_mesh_params(struct sk_buff *skb,
> -       struct genl_info *info)
> +                                  struct genl_info *info)
>  {
>        struct cfg80211_registered_device *rdev = info->user_ptr[0];
> -       struct mesh_config cur_params;
> -       int err;
>        struct net_device *dev = info->user_ptr[1];
> +       struct wireless_dev *wdev = dev->ieee80211_ptr;
> +       struct mesh_config cur_params;
> +       int err = 0;
>        void *hdr;
>        struct nlattr *pinfoattr;
>        struct sk_buff *msg;
>
> +       if (wdev->iftype != NL80211_IFTYPE_MESH_POINT)
> +               return -EOPNOTSUPP;
> +
>        if (!rdev->ops->get_mesh_params)
>                return -EOPNOTSUPP;
>
> -       /* Get the mesh params */
> -       err = rdev->ops->get_mesh_params(&rdev->wiphy, dev, &cur_params);
> +       wdev_lock(wdev);
> +       /* If not connected, get default parameters */
> +       if (!wdev->mesh_id_len)
> +               memcpy(&cur_params, &default_mesh_config, sizeof(cur_params));
> +       else
> +               err = rdev->ops->get_mesh_params(&rdev->wiphy, dev,
> +                                                &cur_params);
> +       wdev_unlock(wdev);
> +
>        if (err)
>                return err;
>
> @@ -2700,23 +2730,37 @@ do {\
>  #undef FILL_IN_MESH_PARAM_IF_SET
>  }
>
> -static int nl80211_set_mesh_params(struct sk_buff *skb, struct genl_info *info)
> +static int nl80211_update_mesh_params(struct sk_buff *skb,
> +                                     struct genl_info *info)
>  {
>        struct cfg80211_registered_device *rdev = info->user_ptr[0];
>        struct net_device *dev = info->user_ptr[1];
> +       struct wireless_dev *wdev = dev->ieee80211_ptr;
>        struct mesh_config cfg;
>        u32 mask;
>        int err;
>
> -       if (!rdev->ops->set_mesh_params)
> +       if (wdev->iftype != NL80211_IFTYPE_MESH_POINT)
> +               return -EOPNOTSUPP;
> +
> +       if (!rdev->ops->update_mesh_params)
>                return -EOPNOTSUPP;
>
>        err = nl80211_parse_mesh_params(info, &cfg, &mask);
>        if (err)
>                return err;
>
> -       /* Apply changes */
> -       return rdev->ops->set_mesh_params(&rdev->wiphy, dev, &cfg, mask);
> +       wdev_lock(wdev);
> +       if (!wdev->mesh_id_len)
> +               err = -ENOLINK;
> +
> +       if (!err)
> +               err = rdev->ops->update_mesh_params(&rdev->wiphy, dev,
> +                                                   mask, &cfg);
> +
> +       wdev_unlock(wdev);
> +
> +       return err;
>  }
>
>  static int nl80211_get_reg(struct sk_buff *skb, struct genl_info *info)
> @@ -4500,6 +4544,41 @@ out:
>        return err;
>  }
>
> +static int nl80211_join_mesh(struct sk_buff *skb, struct genl_info *info)
> +{
> +       struct cfg80211_registered_device *rdev = info->user_ptr[0];
> +       struct net_device *dev = info->user_ptr[1];
> +       struct mesh_config cfg;
> +       int err;
> +
> +       /* start with default */
> +       memcpy(&cfg, &default_mesh_config, sizeof(cfg));
> +
> +       if (info->attrs[NL80211_ATTR_MESH_PARAMS]) {
> +               /* and parse parameters if given */
> +               err = nl80211_parse_mesh_params(info, &cfg, NULL);
> +               if (err)
> +                       return err;
> +       }
> +
> +       if (!info->attrs[NL80211_ATTR_MESH_ID] ||
> +           !nla_len(info->attrs[NL80211_ATTR_MESH_ID]))
> +               return -EINVAL;
> +
> +       return cfg80211_join_mesh(rdev, dev,
> +                                 nla_data(info->attrs[NL80211_ATTR_MESH_ID]),
> +                                 nla_len(info->attrs[NL80211_ATTR_MESH_ID]),
> +                                 &cfg);
> +}
> +
> +static int nl80211_leave_mesh(struct sk_buff *skb, struct genl_info *info)
> +{
> +       struct cfg80211_registered_device *rdev = info->user_ptr[0];
> +       struct net_device *dev = info->user_ptr[1];
> +
> +       return cfg80211_leave_mesh(rdev, dev);
> +}
> +
>  #define NL80211_FLAG_NEED_WIPHY                0x01
>  #define NL80211_FLAG_NEED_NETDEV       0x02
>  #define NL80211_FLAG_NEED_RTNL         0x04
> @@ -4764,10 +4843,10 @@ static struct genl_ops nl80211_ops[] = {
>        },
>        {
>                .cmd = NL80211_CMD_SET_MESH_PARAMS,
> -               .doit = nl80211_set_mesh_params,
> +               .doit = nl80211_update_mesh_params,
>                .policy = nl80211_policy,
>                .flags = GENL_ADMIN_PERM,
> -               .internal_flags = NL80211_FLAG_NEED_NETDEV |
> +               .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
>                                  NL80211_FLAG_NEED_RTNL,
>        },
>        {
> @@ -4982,6 +5061,22 @@ static struct genl_ops nl80211_ops[] = {
>                .internal_flags = NL80211_FLAG_NEED_NETDEV |
>                                  NL80211_FLAG_NEED_RTNL,
>        },
> +       {
> +               .cmd = NL80211_CMD_JOIN_MESH,
> +               .doit = nl80211_join_mesh,
> +               .policy = nl80211_policy,
> +               .flags = GENL_ADMIN_PERM,
> +               .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
> +                                 NL80211_FLAG_NEED_RTNL,
> +       },
> +       {
> +               .cmd = NL80211_CMD_LEAVE_MESH,
> +               .doit = nl80211_leave_mesh,
> +               .policy = nl80211_policy,
> +               .flags = GENL_ADMIN_PERM,
> +               .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
> +                                 NL80211_FLAG_NEED_RTNL,
> +       },
>  };
>
>  static struct genl_multicast_group nl80211_mlme_mcgrp = {
> --- wireless-testing.orig/net/wireless/core.c   2010-12-02 09:32:13.000000000 +0100
> +++ wireless-testing/net/wireless/core.c        2010-12-02 09:38:22.000000000 +0100
> @@ -332,6 +332,7 @@ struct wiphy *wiphy_new(const struct cfg
>        WARN_ON(ops->add_virtual_intf && !ops->del_virtual_intf);
>        WARN_ON(ops->add_station && !ops->del_station);
>        WARN_ON(ops->add_mpath && !ops->del_mpath);
> +       WARN_ON(ops->join_mesh && !ops->leave_mesh);
>
>        alloc_size = sizeof(*rdev) + sizeof_priv;
>
> @@ -752,6 +753,9 @@ static int cfg80211_netdev_notifier_call
>                        cfg80211_mlme_down(rdev, dev);
>                        wdev_unlock(wdev);
>                        break;
> +               case NL80211_IFTYPE_MESH_POINT:
> +                       cfg80211_leave_mesh(rdev, dev);
> +                       break;
>                default:
>                        break;
>                }
> @@ -775,20 +779,27 @@ static int cfg80211_netdev_notifier_call
>                }
>                cfg80211_lock_rdev(rdev);
>                mutex_lock(&rdev->devlist_mtx);
> -#ifdef CONFIG_CFG80211_WEXT
>                wdev_lock(wdev);
>                switch (wdev->iftype) {
> +#ifdef CONFIG_CFG80211_WEXT
>                case NL80211_IFTYPE_ADHOC:
>                        cfg80211_ibss_wext_join(rdev, wdev);
>                        break;
>                case NL80211_IFTYPE_STATION:
>                        cfg80211_mgd_wext_connect(rdev, wdev);
>                        break;
> +#endif
> +               case NL80211_IFTYPE_MESH_POINT:
> +                       /* backward compat code ... */
> +                       if (wdev->mesh_id_up_len)
> +                               __cfg80211_join_mesh(rdev, dev, wdev->ssid,
> +                                                    wdev->mesh_id_up_len,
> +                                                    &default_mesh_config);
> +                       break;
>                default:
>                        break;
>                }
>                wdev_unlock(wdev);
> -#endif
>                rdev->opencount++;
>                mutex_unlock(&rdev->devlist_mtx);
>                cfg80211_unlock_rdev(rdev);
> --- wireless-testing.orig/net/mac80211/cfg.c    2010-12-02 09:32:13.000000000 +0100
> +++ wireless-testing/net/mac80211/cfg.c 2010-12-02 09:38:22.000000000 +0100
> @@ -60,11 +60,6 @@ static int ieee80211_change_iface(struct
>        if (ret)
>                return ret;
>
> -       if (ieee80211_vif_is_mesh(&sdata->vif) && params->mesh_id_len)
> -               ieee80211_sdata_set_mesh_id(sdata,
> -                                           params->mesh_id_len,
> -                                           params->mesh_id);
> -
>        if (type == NL80211_IFTYPE_AP_VLAN &&
>            params && params->use_4addr == 0)
>                rcu_assign_pointer(sdata->u.vlan.sta, NULL);
> @@ -1003,9 +998,9 @@ static inline bool _chg_mesh_attr(enum n
>        return (mask >> (parm-1)) & 0x1;
>  }
>
> -static int ieee80211_set_mesh_params(struct wiphy *wiphy,
> -                               struct net_device *dev,
> -                               const struct mesh_config *nconf, u32 mask)
> +static int ieee80211_update_mesh_params(struct wiphy *wiphy,
> +                                       struct net_device *dev, u32 mask,
> +                                       const struct mesh_config *nconf)
>  {
>        struct mesh_config *conf;
>        struct ieee80211_sub_if_data *sdata;
> @@ -1054,6 +1049,30 @@ static int ieee80211_set_mesh_params(str
>        return 0;
>  }
>
> +static int ieee80211_join_mesh(struct wiphy *wiphy, struct net_device *dev,
> +                              const struct mesh_config *conf,
> +                              const struct mesh_setup *setup)
> +{
> +       struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
> +       struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
> +
> +       memcpy(&sdata->u.mesh.mshcfg, conf, sizeof(struct mesh_config));
> +       ifmsh->mesh_id_len = setup->mesh_id_len;
> +       memcpy(ifmsh->mesh_id, setup->mesh_id, ifmsh->mesh_id_len);
> +
> +       ieee80211_start_mesh(sdata);
> +
> +       return 0;
> +}
> +
> +static int ieee80211_leave_mesh(struct wiphy *wiphy, struct net_device *dev)
> +{
> +       struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
> +
> +       ieee80211_stop_mesh(sdata);
> +
> +       return 0;
> +}
>  #endif
>
>  static int ieee80211_change_bss(struct wiphy *wiphy,
> @@ -1758,8 +1777,10 @@ struct cfg80211_ops mac80211_config_ops
>        .change_mpath = ieee80211_change_mpath,
>        .get_mpath = ieee80211_get_mpath,
>        .dump_mpath = ieee80211_dump_mpath,
> -       .set_mesh_params = ieee80211_set_mesh_params,
> +       .update_mesh_params = ieee80211_update_mesh_params,
>        .get_mesh_params = ieee80211_get_mesh_params,
> +       .join_mesh = ieee80211_join_mesh,
> +       .leave_mesh = ieee80211_leave_mesh,
>  #endif
>        .change_bss = ieee80211_change_bss,
>        .set_txq_params = ieee80211_set_txq_params,
> --- wireless-testing.orig/net/mac80211/ieee80211_i.h    2010-12-02 09:32:13.000000000 +0100
> +++ wireless-testing/net/mac80211/ieee80211_i.h 2010-12-02 09:38:22.000000000 +0100
> @@ -608,19 +608,6 @@ struct ieee80211_sub_if_data *vif_to_sda
>        return container_of(p, struct ieee80211_sub_if_data, vif);
>  }
>
> -static inline void
> -ieee80211_sdata_set_mesh_id(struct ieee80211_sub_if_data *sdata,
> -                           u8 mesh_id_len, u8 *mesh_id)
> -{
> -#ifdef CONFIG_MAC80211_MESH
> -       struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
> -       ifmsh->mesh_id_len = mesh_id_len;
> -       memcpy(ifmsh->mesh_id, mesh_id, mesh_id_len);
> -#else
> -       WARN_ON(1);
> -#endif
> -}
> -
>  enum sdata_queue_type {
>        IEEE80211_SDATA_QUEUE_TYPE_FRAME        = 0,
>        IEEE80211_SDATA_QUEUE_AGG_START         = 1,
> --- wireless-testing.orig/net/mac80211/iface.c  2010-12-02 09:32:13.000000000 +0100
> +++ wireless-testing/net/mac80211/iface.c       2010-12-02 09:38:22.000000000 +0100
> @@ -268,9 +268,7 @@ static int ieee80211_do_open(struct net_
>                                goto err_stop;
>                }
>
> -               if (ieee80211_vif_is_mesh(&sdata->vif)) {
> -                       ieee80211_start_mesh(sdata);
> -               } else if (sdata->vif.type == NL80211_IFTYPE_AP) {
> +               if (sdata->vif.type == NL80211_IFTYPE_AP) {
>                        local->fif_pspoll++;
>                        local->fif_probe_req++;
>
> @@ -495,10 +493,6 @@ static void ieee80211_do_stop(struct iee
>                ieee80211_adjust_monitor_flags(sdata, -1);
>                ieee80211_configure_filter(local);
>                break;
> -       case NL80211_IFTYPE_MESH_POINT:
> -               if (ieee80211_vif_is_mesh(&sdata->vif))
> -                       ieee80211_stop_mesh(sdata);
> -               /* fall through */
>        default:
>                flush_work(&sdata->work);
>                /*
> @@ -1188,12 +1182,6 @@ int ieee80211_if_add(struct ieee80211_lo
>        if (ret)
>                goto fail;
>
> -       if (ieee80211_vif_is_mesh(&sdata->vif) &&
> -           params && params->mesh_id_len)
> -               ieee80211_sdata_set_mesh_id(sdata,
> -                                           params->mesh_id_len,
> -                                           params->mesh_id);
> -
>        mutex_lock(&local->iflist_mtx);
>        list_add_tail_rcu(&sdata->list, &local->interfaces);
>        mutex_unlock(&local->iflist_mtx);
> --- wireless-testing.orig/net/mac80211/mesh.c   2010-12-02 09:32:13.000000000 +0100
> +++ wireless-testing/net/mac80211/mesh.c        2010-12-02 09:38:22.000000000 +0100
> @@ -674,26 +674,6 @@ void ieee80211_mesh_init_sdata(struct ie
>                    ieee80211_mesh_housekeeping_timer,
>                    (unsigned long) sdata);
>
> -       ifmsh->mshcfg.dot11MeshRetryTimeout = MESH_RET_T;
> -       ifmsh->mshcfg.dot11MeshConfirmTimeout = MESH_CONF_T;
> -       ifmsh->mshcfg.dot11MeshHoldingTimeout = MESH_HOLD_T;
> -       ifmsh->mshcfg.dot11MeshMaxRetries = MESH_MAX_RETR;
> -       ifmsh->mshcfg.dot11MeshTTL = MESH_TTL;
> -       ifmsh->mshcfg.auto_open_plinks = true;
> -       ifmsh->mshcfg.dot11MeshMaxPeerLinks =
> -               MESH_MAX_ESTAB_PLINKS;
> -       ifmsh->mshcfg.dot11MeshHWMPactivePathTimeout =
> -               MESH_PATH_TIMEOUT;
> -       ifmsh->mshcfg.dot11MeshHWMPpreqMinInterval =
> -               MESH_PREQ_MIN_INT;
> -       ifmsh->mshcfg.dot11MeshHWMPnetDiameterTraversalTime =
> -               MESH_DIAM_TRAVERSAL_TIME;
> -       ifmsh->mshcfg.dot11MeshHWMPmaxPREQretries =
> -               MESH_MAX_PREQ_RETRIES;
> -       ifmsh->mshcfg.path_refresh_time =
> -               MESH_PATH_REFRESH_TIME;
> -       ifmsh->mshcfg.min_discovery_timeout =
> -               MESH_MIN_DISCOVERY_TIMEOUT;
>        ifmsh->accepting_plinks = true;
>        ifmsh->preq_id = 0;
>        ifmsh->sn = 0;
> --- wireless-testing.orig/net/mac80211/mesh.h   2010-12-02 09:32:13.000000000 +0100
> +++ wireless-testing/net/mac80211/mesh.h        2010-12-02 09:38:22.000000000 +0100
> @@ -175,33 +175,10 @@ struct mesh_rmc {
>  */
>  #define MESH_CFG_CMP_LEN       (IEEE80211_MESH_CONFIG_LEN - 2)
>
> -/* Default values, timeouts in ms */
> -#define MESH_TTL               31
> -#define MESH_MAX_RETR          3
> -#define MESH_RET_T             100
> -#define MESH_CONF_T            100
> -#define MESH_HOLD_T            100
> -
> -#define MESH_PATH_TIMEOUT      5000
> -/* Minimum interval between two consecutive PREQs originated by the same
> - * interface
> - */
> -#define MESH_PREQ_MIN_INT      10
> -#define MESH_DIAM_TRAVERSAL_TIME 50
> -/* A path will be refreshed if it is used PATH_REFRESH_TIME milliseconds before
> - * timing out.  This way it will remain ACTIVE and no data frames will be
> - * unnecesarily held in the pending queue.
> - */
> -#define MESH_PATH_REFRESH_TIME                 1000
> -#define MESH_MIN_DISCOVERY_TIMEOUT (2 * MESH_DIAM_TRAVERSAL_TIME)
>  #define MESH_DEFAULT_BEACON_INTERVAL           1000    /* in 1024 us units */
>
> -#define MESH_MAX_PREQ_RETRIES 4
>  #define MESH_PATH_EXPIRE (600 * HZ)
>
> -/* Default maximum number of established plinks per interface */
> -#define MESH_MAX_ESTAB_PLINKS  32
> -
>  /* Default maximum number of plinks per interface */
>  #define MESH_MAX_PLINKS                256
>
> --- wireless-testing.orig/net/wireless/util.c   2010-12-02 09:32:13.000000000 +0100
> +++ wireless-testing/net/wireless/util.c        2010-12-02 09:38:22.000000000 +0100
> @@ -792,6 +792,7 @@ int cfg80211_change_iface(struct cfg8021
>
>        if (ntype != otype) {
>                dev->ieee80211_ptr->use_4addr = false;
> +               dev->ieee80211_ptr->mesh_id_up_len = 0;
>
>                switch (otype) {
>                case NL80211_IFTYPE_ADHOC:
>
>
>



-- 
Javier Cardona
cozybit Inc.
http://www.cozybit.com
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Host AP]     [ATH6KL]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [Linux Kernel]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Samba]     [Device Mapper]
  Powered by Linux