aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless/mesh.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2010-12-03 03:20:44 -0500
committerJohn W. Linville <linville@tuxdriver.com>2010-12-06 16:01:29 -0500
commit29cbe68c516a48a9a88b3226878570c6cbd83c02 (patch)
tree4774f8a3a244236234a521baa4d1ae5b3e1494ba /net/wireless/mesh.c
parentbd90fdcc5fbd99a2a778999610420cf793bd1be2 (diff)
cfg80211/mac80211: add mesh join/leave commands
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. In mac80211, beaconing must now also follow the mesh enabled/not enabled state, which is done by testing the mesh ID. Signed-off-by: Javier Cardona <javier@cozybit.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/wireless/mesh.c')
-rw-r--r--net/wireless/mesh.c140
1 files changed, 140 insertions, 0 deletions
diff --git a/net/wireless/mesh.c b/net/wireless/mesh.c
new file mode 100644
index 000000000000..e0b9747fe50a
--- /dev/null
+++ b/net/wireless/mesh.c
@@ -0,0 +1,140 @@
1#include <linux/ieee80211.h>
2#include <net/cfg80211.h>
3#include "core.h"
4
5/* Default values, timeouts in ms */
6#define MESH_TTL 31
7#define MESH_DEFAULT_ELEMENT_TTL 31
8#define MESH_MAX_RETR 3
9#define MESH_RET_T 100
10#define MESH_CONF_T 100
11#define MESH_HOLD_T 100
12
13#define MESH_PATH_TIMEOUT 5000
14
15/*
16 * Minimum interval between two consecutive PREQs originated by the same
17 * interface
18 */
19#define MESH_PREQ_MIN_INT 10
20#define MESH_DIAM_TRAVERSAL_TIME 50
21
22/*
23 * A path will be refreshed if it is used PATH_REFRESH_TIME milliseconds
24 * before timing out. This way it will remain ACTIVE and no data frames
25 * will be unnecessarily held in the pending queue.
26 */
27#define MESH_PATH_REFRESH_TIME 1000
28#define MESH_MIN_DISCOVERY_TIMEOUT (2 * MESH_DIAM_TRAVERSAL_TIME)
29
30/* Default maximum number of established plinks per interface */
31#define MESH_MAX_ESTAB_PLINKS 32
32
33#define MESH_MAX_PREQ_RETRIES 4
34
35
36const struct mesh_config default_mesh_config = {
37 .dot11MeshRetryTimeout = MESH_RET_T,
38 .dot11MeshConfirmTimeout = MESH_CONF_T,
39 .dot11MeshHoldingTimeout = MESH_HOLD_T,
40 .dot11MeshMaxRetries = MESH_MAX_RETR,
41 .dot11MeshTTL = MESH_TTL,
42 .element_ttl = MESH_DEFAULT_ELEMENT_TTL,
43 .auto_open_plinks = true,
44 .dot11MeshMaxPeerLinks = MESH_MAX_ESTAB_PLINKS,
45 .dot11MeshHWMPactivePathTimeout = MESH_PATH_TIMEOUT,
46 .dot11MeshHWMPpreqMinInterval = MESH_PREQ_MIN_INT,
47 .dot11MeshHWMPnetDiameterTraversalTime = MESH_DIAM_TRAVERSAL_TIME,
48 .dot11MeshHWMPmaxPREQretries = MESH_MAX_PREQ_RETRIES,
49 .path_refresh_time = MESH_PATH_REFRESH_TIME,
50 .min_discovery_timeout = MESH_MIN_DISCOVERY_TIMEOUT,
51};
52
53
54int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev,
55 struct net_device *dev,
56 const u8 *mesh_id, u8 mesh_id_len,
57 const struct mesh_config *conf)
58{
59 struct wireless_dev *wdev = dev->ieee80211_ptr;
60 struct mesh_setup setup = {
61 .mesh_id = mesh_id,
62 .mesh_id_len = mesh_id_len,
63 };
64 int err;
65
66 BUILD_BUG_ON(IEEE80211_MAX_SSID_LEN != IEEE80211_MAX_MESH_ID_LEN);
67
68 ASSERT_WDEV_LOCK(wdev);
69
70 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT)
71 return -EOPNOTSUPP;
72
73 if (wdev->mesh_id_len)
74 return -EALREADY;
75
76 if (!mesh_id_len)
77 return -EINVAL;
78
79 if (!rdev->ops->join_mesh)
80 return -EOPNOTSUPP;
81
82 err = rdev->ops->join_mesh(&rdev->wiphy, dev, conf, &setup);
83 if (!err) {
84 memcpy(wdev->ssid, mesh_id, mesh_id_len);
85 wdev->mesh_id_len = mesh_id_len;
86 }
87
88 return err;
89}
90
91int cfg80211_join_mesh(struct cfg80211_registered_device *rdev,
92 struct net_device *dev,
93 const u8 *mesh_id, u8 mesh_id_len,
94 const struct mesh_config *conf)
95{
96 struct wireless_dev *wdev = dev->ieee80211_ptr;
97 int err;
98
99 wdev_lock(wdev);
100 err = __cfg80211_join_mesh(rdev, dev, mesh_id, mesh_id_len, conf);
101 wdev_unlock(wdev);
102
103 return err;
104}
105
106static int __cfg80211_leave_mesh(struct cfg80211_registered_device *rdev,
107 struct net_device *dev)
108{
109 struct wireless_dev *wdev = dev->ieee80211_ptr;
110 int err;
111
112 ASSERT_WDEV_LOCK(wdev);
113
114 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT)
115 return -EOPNOTSUPP;
116
117 if (!rdev->ops->leave_mesh)
118 return -EOPNOTSUPP;
119
120 if (!wdev->mesh_id_len)
121 return -ENOTCONN;
122
123 err = rdev->ops->leave_mesh(&rdev->wiphy, dev);
124 if (!err)
125 wdev->mesh_id_len = 0;
126 return err;
127}
128
129int cfg80211_leave_mesh(struct cfg80211_registered_device *rdev,
130 struct net_device *dev)
131{
132 struct wireless_dev *wdev = dev->ieee80211_ptr;
133 int err;
134
135 wdev_lock(wdev);
136 err = __cfg80211_leave_mesh(rdev, dev);
137 wdev_unlock(wdev);
138
139 return err;
140}