Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
mesh.c
Go to the documentation of this file.
1 #include <linux/ieee80211.h>
2 #include <linux/export.h>
3 #include <net/cfg80211.h>
4 #include "nl80211.h"
5 #include "core.h"
6 
7 /* Default values, timeouts in ms */
8 #define MESH_TTL 31
9 #define MESH_DEFAULT_ELEMENT_TTL 31
10 #define MESH_MAX_RETR 3
11 #define MESH_RET_T 100
12 #define MESH_CONF_T 100
13 #define MESH_HOLD_T 100
14 
15 #define MESH_PATH_TIMEOUT 5000
16 #define MESH_RANN_INTERVAL 5000
17 #define MESH_PATH_TO_ROOT_TIMEOUT 6000
18 #define MESH_ROOT_INTERVAL 5000
19 #define MESH_ROOT_CONFIRMATION_INTERVAL 2000
20 
21 /*
22  * Minimum interval between two consecutive PREQs originated by the same
23  * interface
24  */
25 #define MESH_PREQ_MIN_INT 10
26 #define MESH_PERR_MIN_INT 100
27 #define MESH_DIAM_TRAVERSAL_TIME 50
28 
29 #define MESH_RSSI_THRESHOLD 0
30 
31 /*
32  * A path will be refreshed if it is used PATH_REFRESH_TIME milliseconds
33  * before timing out. This way it will remain ACTIVE and no data frames
34  * will be unnecessarily held in the pending queue.
35  */
36 #define MESH_PATH_REFRESH_TIME 1000
37 #define MESH_MIN_DISCOVERY_TIMEOUT (2 * MESH_DIAM_TRAVERSAL_TIME)
38 
39 /* Default maximum number of established plinks per interface */
40 #define MESH_MAX_ESTAB_PLINKS 32
41 
42 #define MESH_MAX_PREQ_RETRIES 4
43 
44 #define MESH_SYNC_NEIGHBOR_OFFSET_MAX 50
45 
47  .dot11MeshRetryTimeout = MESH_RET_T,
48  .dot11MeshConfirmTimeout = MESH_CONF_T,
49  .dot11MeshHoldingTimeout = MESH_HOLD_T,
50  .dot11MeshMaxRetries = MESH_MAX_RETR,
51  .dot11MeshTTL = MESH_TTL,
52  .element_ttl = MESH_DEFAULT_ELEMENT_TTL,
53  .auto_open_plinks = true,
54  .dot11MeshMaxPeerLinks = MESH_MAX_ESTAB_PLINKS,
55  .dot11MeshNbrOffsetMaxNeighbor = MESH_SYNC_NEIGHBOR_OFFSET_MAX,
56  .dot11MeshHWMPactivePathTimeout = MESH_PATH_TIMEOUT,
57  .dot11MeshHWMPpreqMinInterval = MESH_PREQ_MIN_INT,
58  .dot11MeshHWMPperrMinInterval = MESH_PERR_MIN_INT,
59  .dot11MeshHWMPnetDiameterTraversalTime = MESH_DIAM_TRAVERSAL_TIME,
60  .dot11MeshHWMPmaxPREQretries = MESH_MAX_PREQ_RETRIES,
61  .path_refresh_time = MESH_PATH_REFRESH_TIME,
62  .min_discovery_timeout = MESH_MIN_DISCOVERY_TIMEOUT,
63  .dot11MeshHWMPRannInterval = MESH_RANN_INTERVAL,
64  .dot11MeshGateAnnouncementProtocol = false,
65  .dot11MeshForwarding = true,
66  .rssi_threshold = MESH_RSSI_THRESHOLD,
68  .dot11MeshHWMPactivePathToRootTimeout = MESH_PATH_TO_ROOT_TIMEOUT,
69  .dot11MeshHWMProotInterval = MESH_ROOT_INTERVAL,
70  .dot11MeshHWMPconfirmationInterval = MESH_ROOT_CONFIRMATION_INTERVAL,
71 };
72 
74  /* cfg80211_join_mesh() will pick a channel if needed */
75  .channel = NULL,
76  .channel_type = NL80211_CHAN_NO_HT,
78  .path_sel_proto = IEEE80211_PATH_PROTOCOL_HWMP,
79  .path_metric = IEEE80211_PATH_METRIC_AIRTIME,
80  .ie = NULL,
81  .ie_len = 0,
82  .is_secure = false,
83 };
84 
86  struct net_device *dev,
87  struct mesh_setup *setup,
88  const struct mesh_config *conf)
89 {
90  struct wireless_dev *wdev = dev->ieee80211_ptr;
91  int err;
92 
94 
95  ASSERT_WDEV_LOCK(wdev);
96 
97  if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT)
98  return -EOPNOTSUPP;
99 
100  if (!(rdev->wiphy.flags & WIPHY_FLAG_MESH_AUTH) &&
101  setup->is_secure)
102  return -EOPNOTSUPP;
103 
104  if (wdev->mesh_id_len)
105  return -EALREADY;
106 
107  if (!setup->mesh_id_len)
108  return -EINVAL;
109 
110  if (!rdev->ops->join_mesh)
111  return -EOPNOTSUPP;
112 
113  if (!setup->channel) {
114  /* if no channel explicitly given, use preset channel */
115  setup->channel = wdev->preset_chan;
116  setup->channel_type = wdev->preset_chantype;
117  }
118 
119  if (!setup->channel) {
120  /* if we don't have that either, use the first usable channel */
121  enum ieee80211_band band;
122 
123  for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
124  struct ieee80211_supported_band *sband;
125  struct ieee80211_channel *chan;
126  int i;
127 
128  sband = rdev->wiphy.bands[band];
129  if (!sband)
130  continue;
131 
132  for (i = 0; i < sband->n_channels; i++) {
133  chan = &sband->channels[i];
134  if (chan->flags & (IEEE80211_CHAN_NO_IBSS |
138  continue;
139  setup->channel = chan;
140  break;
141  }
142 
143  if (setup->channel)
144  break;
145  }
146 
147  /* no usable channel ... */
148  if (!setup->channel)
149  return -EINVAL;
150 
152  }
153 
154  if (!cfg80211_can_beacon_sec_chan(&rdev->wiphy, setup->channel,
155  setup->channel_type))
156  return -EINVAL;
157 
158  err = cfg80211_can_use_chan(rdev, wdev, setup->channel,
160  if (err)
161  return err;
162 
163  err = rdev->ops->join_mesh(&rdev->wiphy, dev, conf, setup);
164  if (!err) {
165  memcpy(wdev->ssid, setup->mesh_id, setup->mesh_id_len);
166  wdev->mesh_id_len = setup->mesh_id_len;
167  wdev->channel = setup->channel;
168  }
169 
170  return err;
171 }
172 
174  struct net_device *dev,
175  struct mesh_setup *setup,
176  const struct mesh_config *conf)
177 {
178  struct wireless_dev *wdev = dev->ieee80211_ptr;
179  int err;
180 
181  mutex_lock(&rdev->devlist_mtx);
182  wdev_lock(wdev);
183  err = __cfg80211_join_mesh(rdev, dev, setup, conf);
184  wdev_unlock(wdev);
185  mutex_unlock(&rdev->devlist_mtx);
186 
187  return err;
188 }
189 
191  struct wireless_dev *wdev, int freq,
193 {
194  struct ieee80211_channel *channel;
195  int err;
196 
197  channel = rdev_freq_to_chan(rdev, freq, channel_type);
198  if (!channel || !cfg80211_can_beacon_sec_chan(&rdev->wiphy,
199  channel,
200  channel_type)) {
201  return -EINVAL;
202  }
203 
204  /*
205  * Workaround for libertas (only!), it puts the interface
206  * into mesh mode but doesn't implement join_mesh. Instead,
207  * it is configured via sysfs and then joins the mesh when
208  * you set the channel. Note that the libertas mesh isn't
209  * compatible with 802.11 mesh.
210  */
211  if (rdev->ops->libertas_set_mesh_channel) {
212  if (channel_type != NL80211_CHAN_NO_HT)
213  return -EINVAL;
214 
215  if (!netif_running(wdev->netdev))
216  return -ENETDOWN;
217 
218  err = cfg80211_can_use_chan(rdev, wdev, channel,
220  if (err)
221  return err;
222 
223  err = rdev->ops->libertas_set_mesh_channel(&rdev->wiphy,
224  wdev->netdev,
225  channel);
226  if (!err)
227  wdev->channel = channel;
228 
229  return err;
230  }
231 
232  if (wdev->mesh_id_len)
233  return -EBUSY;
234 
235  wdev->preset_chan = channel;
237  return 0;
238 }
239 
241  const u8 *macaddr, const u8* ie, u8 ie_len, gfp_t gfp)
242 {
243  struct wireless_dev *wdev = dev->ieee80211_ptr;
244 
246  return;
247 
248  nl80211_send_new_peer_candidate(wiphy_to_dev(wdev->wiphy), dev,
249  macaddr, ie, ie_len, gfp);
250 }
252 
253 static int __cfg80211_leave_mesh(struct cfg80211_registered_device *rdev,
254  struct net_device *dev)
255 {
256  struct wireless_dev *wdev = dev->ieee80211_ptr;
257  int err;
258 
259  ASSERT_WDEV_LOCK(wdev);
260 
261  if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT)
262  return -EOPNOTSUPP;
263 
264  if (!rdev->ops->leave_mesh)
265  return -EOPNOTSUPP;
266 
267  if (!wdev->mesh_id_len)
268  return -ENOTCONN;
269 
270  err = rdev->ops->leave_mesh(&rdev->wiphy, dev);
271  if (!err) {
272  wdev->mesh_id_len = 0;
273  wdev->channel = NULL;
274  }
275 
276  return err;
277 }
278 
280  struct net_device *dev)
281 {
282  struct wireless_dev *wdev = dev->ieee80211_ptr;
283  int err;
284 
285  wdev_lock(wdev);
286  err = __cfg80211_leave_mesh(rdev, dev);
287  wdev_unlock(wdev);
288 
289  return err;
290 }