aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2008-09-10 18:01:49 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-09-15 16:48:20 -0400
commit472dbc45dc1966284de72d7de15690c17ed2cf33 (patch)
treee8bfb88067f7fd8845978d1613f868e6a4499999
parent7c95069522d02ff144cd421be6618dce619caf7e (diff)
mac80211: split off mesh handling entirely
This patch splits off mesh handling from the STA/IBSS. Unfortunately it increases mesh code size a bit, but I think it makes things clearer. The patch also reduces per-interface run-time memory usage. Also clean up a few places where ifdef is not required. Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--net/mac80211/cfg.c6
-rw-r--r--net/mac80211/debugfs_netdev.c38
-rw-r--r--net/mac80211/ieee80211_i.h101
-rw-r--r--net/mac80211/iface.c13
-rw-r--r--net/mac80211/main.c13
-rw-r--r--net/mac80211/mesh.c328
-rw-r--r--net/mac80211/mesh.h15
-rw-r--r--net/mac80211/mesh_hwmp.c98
-rw-r--r--net/mac80211/mesh_pathtbl.c8
-rw-r--r--net/mac80211/mesh_plink.c18
-rw-r--r--net/mac80211/mlme.c83
-rw-r--r--net/mac80211/rc80211_pid_algo.c7
-rw-r--r--net/mac80211/rx.c8
-rw-r--r--net/mac80211/scan.c1
-rw-r--r--net/mac80211/tx.c15
15 files changed, 457 insertions, 295 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 5a3bdaad6c19..6ec2127f9a60 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -116,9 +116,9 @@ static int ieee80211_change_iface(struct wiphy *wiphy, int ifindex,
116 return ret; 116 return ret;
117 117
118 if (ieee80211_vif_is_mesh(&sdata->vif) && params->mesh_id_len) 118 if (ieee80211_vif_is_mesh(&sdata->vif) && params->mesh_id_len)
119 ieee80211_if_sta_set_mesh_id(&sdata->u.sta, 119 ieee80211_sdata_set_mesh_id(sdata,
120 params->mesh_id_len, 120 params->mesh_id_len,
121 params->mesh_id); 121 params->mesh_id);
122 122
123 if (sdata->vif.type != IEEE80211_IF_TYPE_MNTR || !flags) 123 if (sdata->vif.type != IEEE80211_IF_TYPE_MNTR || !flags)
124 return 0; 124 return 0;
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c
index 8165df578c92..0fa7681a3d20 100644
--- a/net/mac80211/debugfs_netdev.c
+++ b/net/mac80211/debugfs_netdev.c
@@ -207,37 +207,37 @@ IEEE80211_IF_FILE(peer, u.wds.remote_addr, MAC);
207 207
208#ifdef CONFIG_MAC80211_MESH 208#ifdef CONFIG_MAC80211_MESH
209/* Mesh stats attributes */ 209/* Mesh stats attributes */
210IEEE80211_IF_FILE(fwded_frames, u.sta.mshstats.fwded_frames, DEC); 210IEEE80211_IF_FILE(fwded_frames, u.mesh.mshstats.fwded_frames, DEC);
211IEEE80211_IF_FILE(dropped_frames_ttl, u.sta.mshstats.dropped_frames_ttl, DEC); 211IEEE80211_IF_FILE(dropped_frames_ttl, u.mesh.mshstats.dropped_frames_ttl, DEC);
212IEEE80211_IF_FILE(dropped_frames_no_route, 212IEEE80211_IF_FILE(dropped_frames_no_route,
213 u.sta.mshstats.dropped_frames_no_route, DEC); 213 u.mesh.mshstats.dropped_frames_no_route, DEC);
214IEEE80211_IF_FILE(estab_plinks, u.sta.mshstats.estab_plinks, ATOMIC); 214IEEE80211_IF_FILE(estab_plinks, u.mesh.mshstats.estab_plinks, ATOMIC);
215 215
216/* Mesh parameters */ 216/* Mesh parameters */
217IEEE80211_IF_WFILE(dot11MeshMaxRetries, 217IEEE80211_IF_WFILE(dot11MeshMaxRetries,
218 u.sta.mshcfg.dot11MeshMaxRetries, DEC, u8); 218 u.mesh.mshcfg.dot11MeshMaxRetries, DEC, u8);
219IEEE80211_IF_WFILE(dot11MeshRetryTimeout, 219IEEE80211_IF_WFILE(dot11MeshRetryTimeout,
220 u.sta.mshcfg.dot11MeshRetryTimeout, DEC, u16); 220 u.mesh.mshcfg.dot11MeshRetryTimeout, DEC, u16);
221IEEE80211_IF_WFILE(dot11MeshConfirmTimeout, 221IEEE80211_IF_WFILE(dot11MeshConfirmTimeout,
222 u.sta.mshcfg.dot11MeshConfirmTimeout, DEC, u16); 222 u.mesh.mshcfg.dot11MeshConfirmTimeout, DEC, u16);
223IEEE80211_IF_WFILE(dot11MeshHoldingTimeout, 223IEEE80211_IF_WFILE(dot11MeshHoldingTimeout,
224 u.sta.mshcfg.dot11MeshHoldingTimeout, DEC, u16); 224 u.mesh.mshcfg.dot11MeshHoldingTimeout, DEC, u16);
225IEEE80211_IF_WFILE(dot11MeshTTL, u.sta.mshcfg.dot11MeshTTL, DEC, u8); 225IEEE80211_IF_WFILE(dot11MeshTTL, u.mesh.mshcfg.dot11MeshTTL, DEC, u8);
226IEEE80211_IF_WFILE(auto_open_plinks, u.sta.mshcfg.auto_open_plinks, DEC, u8); 226IEEE80211_IF_WFILE(auto_open_plinks, u.mesh.mshcfg.auto_open_plinks, DEC, u8);
227IEEE80211_IF_WFILE(dot11MeshMaxPeerLinks, 227IEEE80211_IF_WFILE(dot11MeshMaxPeerLinks,
228 u.sta.mshcfg.dot11MeshMaxPeerLinks, DEC, u16); 228 u.mesh.mshcfg.dot11MeshMaxPeerLinks, DEC, u16);
229IEEE80211_IF_WFILE(dot11MeshHWMPactivePathTimeout, 229IEEE80211_IF_WFILE(dot11MeshHWMPactivePathTimeout,
230 u.sta.mshcfg.dot11MeshHWMPactivePathTimeout, DEC, u32); 230 u.mesh.mshcfg.dot11MeshHWMPactivePathTimeout, DEC, u32);
231IEEE80211_IF_WFILE(dot11MeshHWMPpreqMinInterval, 231IEEE80211_IF_WFILE(dot11MeshHWMPpreqMinInterval,
232 u.sta.mshcfg.dot11MeshHWMPpreqMinInterval, DEC, u16); 232 u.mesh.mshcfg.dot11MeshHWMPpreqMinInterval, DEC, u16);
233IEEE80211_IF_WFILE(dot11MeshHWMPnetDiameterTraversalTime, 233IEEE80211_IF_WFILE(dot11MeshHWMPnetDiameterTraversalTime,
234 u.sta.mshcfg.dot11MeshHWMPnetDiameterTraversalTime, DEC, u16); 234 u.mesh.mshcfg.dot11MeshHWMPnetDiameterTraversalTime, DEC, u16);
235IEEE80211_IF_WFILE(dot11MeshHWMPmaxPREQretries, 235IEEE80211_IF_WFILE(dot11MeshHWMPmaxPREQretries,
236 u.sta.mshcfg.dot11MeshHWMPmaxPREQretries, DEC, u8); 236 u.mesh.mshcfg.dot11MeshHWMPmaxPREQretries, DEC, u8);
237IEEE80211_IF_WFILE(path_refresh_time, 237IEEE80211_IF_WFILE(path_refresh_time,
238 u.sta.mshcfg.path_refresh_time, DEC, u32); 238 u.mesh.mshcfg.path_refresh_time, DEC, u32);
239IEEE80211_IF_WFILE(min_discovery_timeout, 239IEEE80211_IF_WFILE(min_discovery_timeout,
240 u.sta.mshcfg.min_discovery_timeout, DEC, u16); 240 u.mesh.mshcfg.min_discovery_timeout, DEC, u16);
241#endif 241#endif
242 242
243 243
@@ -350,7 +350,7 @@ static void add_files(struct ieee80211_sub_if_data *sdata)
350 add_mesh_stats(sdata); 350 add_mesh_stats(sdata);
351 add_mesh_config(sdata); 351 add_mesh_config(sdata);
352#endif 352#endif
353 /* fall through */ 353 break;
354 case IEEE80211_IF_TYPE_STA: 354 case IEEE80211_IF_TYPE_STA:
355 case IEEE80211_IF_TYPE_IBSS: 355 case IEEE80211_IF_TYPE_IBSS:
356 add_sta_files(sdata); 356 add_sta_files(sdata);
@@ -487,7 +487,7 @@ static void del_files(struct ieee80211_sub_if_data *sdata)
487 del_mesh_stats(sdata); 487 del_mesh_stats(sdata);
488 del_mesh_config(sdata); 488 del_mesh_config(sdata);
489#endif 489#endif
490 /* fall through */ 490 break;
491 case IEEE80211_IF_TYPE_STA: 491 case IEEE80211_IF_TYPE_STA:
492 case IEEE80211_IF_TYPE_IBSS: 492 case IEEE80211_IF_TYPE_IBSS:
493 del_sta_files(sdata); 493 del_sta_files(sdata);
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 6f334e4c3d66..cac0b1334548 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -308,7 +308,6 @@ enum ieee80211_sta_mlme_state {
308 IEEE80211_STA_MLME_ASSOCIATED, 308 IEEE80211_STA_MLME_ASSOCIATED,
309 IEEE80211_STA_MLME_IBSS_SEARCH, 309 IEEE80211_STA_MLME_IBSS_SEARCH,
310 IEEE80211_STA_MLME_IBSS_JOINED, 310 IEEE80211_STA_MLME_IBSS_JOINED,
311 IEEE80211_STA_MLME_MESH_UP
312}; 311};
313 312
314/* bitfield of allowed auth algs */ 313/* bitfield of allowed auth algs */
@@ -325,34 +324,6 @@ struct ieee80211_if_sta {
325 size_t ssid_len; 324 size_t ssid_len;
326 u8 scan_ssid[IEEE80211_MAX_SSID_LEN]; 325 u8 scan_ssid[IEEE80211_MAX_SSID_LEN];
327 size_t scan_ssid_len; 326 size_t scan_ssid_len;
328#ifdef CONFIG_MAC80211_MESH
329 struct timer_list mesh_path_timer;
330 u8 mesh_id[IEEE80211_MAX_MESH_ID_LEN];
331 size_t mesh_id_len;
332 /* Active Path Selection Protocol Identifier */
333 u8 mesh_pp_id[4];
334 /* Active Path Selection Metric Identifier */
335 u8 mesh_pm_id[4];
336 /* Congestion Control Mode Identifier */
337 u8 mesh_cc_id[4];
338 /* Local mesh Destination Sequence Number */
339 u32 dsn;
340 /* Last used PREQ ID */
341 u32 preq_id;
342 atomic_t mpaths;
343 /* Timestamp of last DSN update */
344 unsigned long last_dsn_update;
345 /* Timestamp of last DSN sent */
346 unsigned long last_preq;
347 struct mesh_rmc *rmc;
348 spinlock_t mesh_preq_queue_lock;
349 struct mesh_preq_queue preq_queue;
350 int preq_queue_len;
351 struct mesh_stats mshstats;
352 struct mesh_config mshcfg;
353 u32 mesh_seqnum;
354 bool accepting_plinks;
355#endif
356 u16 aid; 327 u16 aid;
357 u16 ap_capab, capab; 328 u16 ap_capab, capab;
358 u8 *extra_ie; /* to be added to the end of AssocReq */ 329 u8 *extra_ie; /* to be added to the end of AssocReq */
@@ -387,20 +358,47 @@ struct ieee80211_if_sta {
387 int num_beacons; /* number of TXed beacon frames by this STA */ 358 int num_beacons; /* number of TXed beacon frames by this STA */
388}; 359};
389 360
390static inline void ieee80211_if_sta_set_mesh_id(struct ieee80211_if_sta *ifsta, 361struct ieee80211_if_mesh {
391 u8 mesh_id_len, u8 *mesh_id) 362 struct work_struct work;
392{ 363 struct timer_list housekeeping_timer;
393#ifdef CONFIG_MAC80211_MESH 364 struct timer_list mesh_path_timer;
394 ifsta->mesh_id_len = mesh_id_len; 365 struct sk_buff_head skb_queue;
395 memcpy(ifsta->mesh_id, mesh_id, mesh_id_len); 366
396#endif 367 bool housekeeping;
397} 368
369 u8 mesh_id[IEEE80211_MAX_MESH_ID_LEN];
370 size_t mesh_id_len;
371 /* Active Path Selection Protocol Identifier */
372 u8 mesh_pp_id[4];
373 /* Active Path Selection Metric Identifier */
374 u8 mesh_pm_id[4];
375 /* Congestion Control Mode Identifier */
376 u8 mesh_cc_id[4];
377 /* Local mesh Destination Sequence Number */
378 u32 dsn;
379 /* Last used PREQ ID */
380 u32 preq_id;
381 atomic_t mpaths;
382 /* Timestamp of last DSN update */
383 unsigned long last_dsn_update;
384 /* Timestamp of last DSN sent */
385 unsigned long last_preq;
386 struct mesh_rmc *rmc;
387 spinlock_t mesh_preq_queue_lock;
388 struct mesh_preq_queue preq_queue;
389 int preq_queue_len;
390 struct mesh_stats mshstats;
391 struct mesh_config mshcfg;
392 u32 mesh_seqnum;
393 bool accepting_plinks;
394 int num_beacons;
395};
398 396
399#ifdef CONFIG_MAC80211_MESH 397#ifdef CONFIG_MAC80211_MESH
400#define IEEE80211_IFSTA_MESH_CTR_INC(sta, name) \ 398#define IEEE80211_IFSTA_MESH_CTR_INC(msh, name) \
401 do { (sta)->mshstats.name++; } while (0) 399 do { (msh)->mshstats.name++; } while (0)
402#else 400#else
403#define IEEE80211_IFSTA_MESH_CTR_INC(sta, name) \ 401#define IEEE80211_IFSTA_MESH_CTR_INC(msh, name) \
404 do { } while (0) 402 do { } while (0)
405#endif 403#endif
406 404
@@ -455,6 +453,9 @@ struct ieee80211_sub_if_data {
455 struct ieee80211_if_wds wds; 453 struct ieee80211_if_wds wds;
456 struct ieee80211_if_vlan vlan; 454 struct ieee80211_if_vlan vlan;
457 struct ieee80211_if_sta sta; 455 struct ieee80211_if_sta sta;
456#ifdef CONFIG_MAC80211_MESH
457 struct ieee80211_if_mesh mesh;
458#endif
458 u32 mntr_flags; 459 u32 mntr_flags;
459 } u; 460 } u;
460 461
@@ -548,6 +549,19 @@ struct ieee80211_sub_if_data *vif_to_sdata(struct ieee80211_vif *p)
548 return container_of(p, struct ieee80211_sub_if_data, vif); 549 return container_of(p, struct ieee80211_sub_if_data, vif);
549} 550}
550 551
552static inline void
553ieee80211_sdata_set_mesh_id(struct ieee80211_sub_if_data *sdata,
554 u8 mesh_id_len, u8 *mesh_id)
555{
556#ifdef CONFIG_MAC80211_MESH
557 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
558 ifmsh->mesh_id_len = mesh_id_len;
559 memcpy(ifmsh->mesh_id, mesh_id, mesh_id_len);
560#else
561 WARN_ON(1);
562#endif
563}
564
551enum { 565enum {
552 IEEE80211_RX_MSG = 1, 566 IEEE80211_RX_MSG = 1,
553 IEEE80211_TX_STATUS_MSG = 2, 567 IEEE80211_TX_STATUS_MSG = 2,
@@ -935,13 +949,6 @@ ieee80211_rx_bss_get(struct ieee80211_local *local, u8 *bssid, int freq,
935void ieee80211_rx_bss_put(struct ieee80211_local *local, 949void ieee80211_rx_bss_put(struct ieee80211_local *local,
936 struct ieee80211_sta_bss *bss); 950 struct ieee80211_sta_bss *bss);
937 951
938#ifdef CONFIG_MAC80211_MESH
939void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata);
940#else
941static inline void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata)
942{}
943#endif
944
945/* interface handling */ 952/* interface handling */
946void ieee80211_if_setup(struct net_device *dev); 953void ieee80211_if_setup(struct net_device *dev);
947int ieee80211_if_add(struct ieee80211_local *local, const char *name, 954int ieee80211_if_add(struct ieee80211_local *local, const char *name,
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 672cec60a2fb..ddbaa417e2ec 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -54,10 +54,9 @@ static void ieee80211_teardown_sdata(struct net_device *dev)
54 54
55 break; 55 break;
56 case IEEE80211_IF_TYPE_MESH_POINT: 56 case IEEE80211_IF_TYPE_MESH_POINT:
57 /* Allow compiler to elide mesh_rmc_free call. */
58 if (ieee80211_vif_is_mesh(&sdata->vif)) 57 if (ieee80211_vif_is_mesh(&sdata->vif))
59 mesh_rmc_free(sdata); 58 mesh_rmc_free(sdata);
60 /* fall through */ 59 break;
61 case IEEE80211_IF_TYPE_STA: 60 case IEEE80211_IF_TYPE_STA:
62 case IEEE80211_IF_TYPE_IBSS: 61 case IEEE80211_IF_TYPE_IBSS:
63 kfree(sdata->u.sta.extra_ie); 62 kfree(sdata->u.sta.extra_ie);
@@ -100,7 +99,6 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata,
100 skb_queue_head_init(&sdata->u.ap.ps_bc_buf); 99 skb_queue_head_init(&sdata->u.ap.ps_bc_buf);
101 INIT_LIST_HEAD(&sdata->u.ap.vlans); 100 INIT_LIST_HEAD(&sdata->u.ap.vlans);
102 break; 101 break;
103 case IEEE80211_IF_TYPE_MESH_POINT:
104 case IEEE80211_IF_TYPE_STA: 102 case IEEE80211_IF_TYPE_STA:
105 case IEEE80211_IF_TYPE_IBSS: 103 case IEEE80211_IF_TYPE_IBSS:
106 ifsta = &sdata->u.sta; 104 ifsta = &sdata->u.sta;
@@ -117,7 +115,8 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata,
117 IEEE80211_STA_AUTO_CHANNEL_SEL; 115 IEEE80211_STA_AUTO_CHANNEL_SEL;
118 if (ieee80211_num_regular_queues(&sdata->local->hw) >= 4) 116 if (ieee80211_num_regular_queues(&sdata->local->hw) >= 4)
119 ifsta->flags |= IEEE80211_STA_WMM_ENABLED; 117 ifsta->flags |= IEEE80211_STA_WMM_ENABLED;
120 118 break;
119 case IEEE80211_IF_TYPE_MESH_POINT:
121 if (ieee80211_vif_is_mesh(&sdata->vif)) 120 if (ieee80211_vif_is_mesh(&sdata->vif))
122 ieee80211_mesh_init_sdata(sdata); 121 ieee80211_mesh_init_sdata(sdata);
123 break; 122 break;
@@ -225,9 +224,9 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name,
225 224
226 if (ieee80211_vif_is_mesh(&sdata->vif) && 225 if (ieee80211_vif_is_mesh(&sdata->vif) &&
227 params && params->mesh_id_len) 226 params && params->mesh_id_len)
228 ieee80211_if_sta_set_mesh_id(&sdata->u.sta, 227 ieee80211_sdata_set_mesh_id(sdata,
229 params->mesh_id_len, 228 params->mesh_id_len,
230 params->mesh_id); 229 params->mesh_id);
231 230
232 list_add_tail_rcu(&sdata->list, &local->interfaces); 231 list_add_tail_rcu(&sdata->list, &local->interfaces);
233 232
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 6a7f4fae18c2..522fe6176485 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -252,6 +252,8 @@ static int ieee80211_open(struct net_device *dev)
252 sdata->bss = &sdata->u.ap; 252 sdata->bss = &sdata->u.ap;
253 break; 253 break;
254 case IEEE80211_IF_TYPE_MESH_POINT: 254 case IEEE80211_IF_TYPE_MESH_POINT:
255 if (!ieee80211_vif_is_mesh(&sdata->vif))
256 break;
255 /* mesh ifaces must set allmulti to forward mcast traffic */ 257 /* mesh ifaces must set allmulti to forward mcast traffic */
256 atomic_inc(&local->iff_allmultis); 258 atomic_inc(&local->iff_allmultis);
257 break; 259 break;
@@ -540,10 +542,6 @@ static int ieee80211_stop(struct net_device *dev)
540 ieee80211_configure_filter(local); 542 ieee80211_configure_filter(local);
541 netif_addr_unlock_bh(local->mdev); 543 netif_addr_unlock_bh(local->mdev);
542 break; 544 break;
543 case IEEE80211_IF_TYPE_MESH_POINT:
544 /* allmulti is always set on mesh ifaces */
545 atomic_dec(&local->iff_allmultis);
546 /* fall through */
547 case IEEE80211_IF_TYPE_STA: 545 case IEEE80211_IF_TYPE_STA:
548 case IEEE80211_IF_TYPE_IBSS: 546 case IEEE80211_IF_TYPE_IBSS:
549 sdata->u.sta.state = IEEE80211_STA_MLME_DISABLED; 547 sdata->u.sta.state = IEEE80211_STA_MLME_DISABLED;
@@ -571,6 +569,13 @@ static int ieee80211_stop(struct net_device *dev)
571 sdata->u.sta.extra_ie = NULL; 569 sdata->u.sta.extra_ie = NULL;
572 sdata->u.sta.extra_ie_len = 0; 570 sdata->u.sta.extra_ie_len = 0;
573 /* fall through */ 571 /* fall through */
572 case IEEE80211_IF_TYPE_MESH_POINT:
573 if (ieee80211_vif_is_mesh(&sdata->vif)) {
574 /* allmulti is always set on mesh ifaces */
575 atomic_dec(&local->iff_allmultis);
576 ieee80211_stop_mesh(sdata);
577 }
578 /* fall through */
574 default: 579 default:
575 conf.vif = &sdata->vif; 580 conf.vif = &sdata->vif;
576 conf.type = sdata->vif.type; 581 conf.type = sdata->vif.type;
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index 3ccb3599c04f..9e47725cc592 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -12,6 +12,9 @@
12#include "ieee80211_i.h" 12#include "ieee80211_i.h"
13#include "mesh.h" 13#include "mesh.h"
14 14
15#define IEEE80211_MESH_PEER_INACTIVITY_LIMIT (1800 * HZ)
16#define IEEE80211_MESH_HOUSEKEEPING_INTERVAL (60 * HZ)
17
15#define PP_OFFSET 1 /* Path Selection Protocol */ 18#define PP_OFFSET 1 /* Path Selection Protocol */
16#define PM_OFFSET 5 /* Path Selection Metric */ 19#define PM_OFFSET 5 /* Path Selection Metric */
17#define CC_OFFSET 9 /* Congestion Control Mode */ 20#define CC_OFFSET 9 /* Congestion Control Mode */
@@ -35,6 +38,16 @@ void ieee80211s_stop(void)
35 kmem_cache_destroy(rm_cache); 38 kmem_cache_destroy(rm_cache);
36} 39}
37 40
41static void ieee80211_mesh_housekeeping_timer(unsigned long data)
42{
43 struct ieee80211_sub_if_data *sdata = (void *) data;
44 struct ieee80211_local *local = sdata->local;
45 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
46
47 ifmsh->housekeeping = true;
48 queue_work(local->hw.workqueue, &ifmsh->work);
49}
50
38/** 51/**
39 * mesh_matches_local - check if the config of a mesh point matches ours 52 * mesh_matches_local - check if the config of a mesh point matches ours
40 * 53 *
@@ -46,7 +59,7 @@ void ieee80211s_stop(void)
46 */ 59 */
47bool mesh_matches_local(struct ieee802_11_elems *ie, struct ieee80211_sub_if_data *sdata) 60bool mesh_matches_local(struct ieee802_11_elems *ie, struct ieee80211_sub_if_data *sdata)
48{ 61{
49 struct ieee80211_if_sta *sta = &sdata->u.sta; 62 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
50 63
51 /* 64 /*
52 * As support for each feature is added, check for matching 65 * As support for each feature is added, check for matching
@@ -58,11 +71,11 @@ bool mesh_matches_local(struct ieee802_11_elems *ie, struct ieee80211_sub_if_dat
58 * - MDA enabled 71 * - MDA enabled
59 * - Power management control on fc 72 * - Power management control on fc
60 */ 73 */
61 if (sta->mesh_id_len == ie->mesh_id_len && 74 if (ifmsh->mesh_id_len == ie->mesh_id_len &&
62 memcmp(sta->mesh_id, ie->mesh_id, ie->mesh_id_len) == 0 && 75 memcmp(ifmsh->mesh_id, ie->mesh_id, ie->mesh_id_len) == 0 &&
63 memcmp(sta->mesh_pp_id, ie->mesh_config + PP_OFFSET, 4) == 0 && 76 memcmp(ifmsh->mesh_pp_id, ie->mesh_config + PP_OFFSET, 4) == 0 &&
64 memcmp(sta->mesh_pm_id, ie->mesh_config + PM_OFFSET, 4) == 0 && 77 memcmp(ifmsh->mesh_pm_id, ie->mesh_config + PM_OFFSET, 4) == 0 &&
65 memcmp(sta->mesh_cc_id, ie->mesh_config + CC_OFFSET, 4) == 0) 78 memcmp(ifmsh->mesh_cc_id, ie->mesh_config + CC_OFFSET, 4) == 0)
66 return true; 79 return true;
67 80
68 return false; 81 return false;
@@ -95,11 +108,11 @@ void mesh_accept_plinks_update(struct ieee80211_sub_if_data *sdata)
95 */ 108 */
96 free_plinks = mesh_plink_availables(sdata); 109 free_plinks = mesh_plink_availables(sdata);
97 110
98 if (free_plinks != sdata->u.sta.accepting_plinks) 111 if (free_plinks != sdata->u.mesh.accepting_plinks)
99 ieee80211_sta_timer((unsigned long) sdata); 112 ieee80211_mesh_housekeeping_timer((unsigned long) sdata);
100} 113}
101 114
102void mesh_ids_set_default(struct ieee80211_if_sta *sta) 115void mesh_ids_set_default(struct ieee80211_if_mesh *sta)
103{ 116{
104 u8 def_id[4] = {0x00, 0x0F, 0xAC, 0xff}; 117 u8 def_id[4] = {0x00, 0x0F, 0xAC, 0xff};
105 118
@@ -112,22 +125,22 @@ int mesh_rmc_init(struct ieee80211_sub_if_data *sdata)
112{ 125{
113 int i; 126 int i;
114 127
115 sdata->u.sta.rmc = kmalloc(sizeof(struct mesh_rmc), GFP_KERNEL); 128 sdata->u.mesh.rmc = kmalloc(sizeof(struct mesh_rmc), GFP_KERNEL);
116 if (!sdata->u.sta.rmc) 129 if (!sdata->u.mesh.rmc)
117 return -ENOMEM; 130 return -ENOMEM;
118 sdata->u.sta.rmc->idx_mask = RMC_BUCKETS - 1; 131 sdata->u.mesh.rmc->idx_mask = RMC_BUCKETS - 1;
119 for (i = 0; i < RMC_BUCKETS; i++) 132 for (i = 0; i < RMC_BUCKETS; i++)
120 INIT_LIST_HEAD(&sdata->u.sta.rmc->bucket[i].list); 133 INIT_LIST_HEAD(&sdata->u.mesh.rmc->bucket[i].list);
121 return 0; 134 return 0;
122} 135}
123 136
124void mesh_rmc_free(struct ieee80211_sub_if_data *sdata) 137void mesh_rmc_free(struct ieee80211_sub_if_data *sdata)
125{ 138{
126 struct mesh_rmc *rmc = sdata->u.sta.rmc; 139 struct mesh_rmc *rmc = sdata->u.mesh.rmc;
127 struct rmc_entry *p, *n; 140 struct rmc_entry *p, *n;
128 int i; 141 int i;
129 142
130 if (!sdata->u.sta.rmc) 143 if (!sdata->u.mesh.rmc)
131 return; 144 return;
132 145
133 for (i = 0; i < RMC_BUCKETS; i++) 146 for (i = 0; i < RMC_BUCKETS; i++)
@@ -137,7 +150,7 @@ void mesh_rmc_free(struct ieee80211_sub_if_data *sdata)
137 } 150 }
138 151
139 kfree(rmc); 152 kfree(rmc);
140 sdata->u.sta.rmc = NULL; 153 sdata->u.mesh.rmc = NULL;
141} 154}
142 155
143/** 156/**
@@ -155,7 +168,7 @@ void mesh_rmc_free(struct ieee80211_sub_if_data *sdata)
155int mesh_rmc_check(u8 *sa, struct ieee80211s_hdr *mesh_hdr, 168int mesh_rmc_check(u8 *sa, struct ieee80211s_hdr *mesh_hdr,
156 struct ieee80211_sub_if_data *sdata) 169 struct ieee80211_sub_if_data *sdata)
157{ 170{
158 struct mesh_rmc *rmc = sdata->u.sta.rmc; 171 struct mesh_rmc *rmc = sdata->u.mesh.rmc;
159 u32 seqnum = 0; 172 u32 seqnum = 0;
160 int entries = 0; 173 int entries = 0;
161 u8 idx; 174 u8 idx;
@@ -217,11 +230,11 @@ void mesh_mgmt_ies_add(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata)
217 } 230 }
218 } 231 }
219 232
220 pos = skb_put(skb, 2 + sdata->u.sta.mesh_id_len); 233 pos = skb_put(skb, 2 + sdata->u.mesh.mesh_id_len);
221 *pos++ = WLAN_EID_MESH_ID; 234 *pos++ = WLAN_EID_MESH_ID;
222 *pos++ = sdata->u.sta.mesh_id_len; 235 *pos++ = sdata->u.mesh.mesh_id_len;
223 if (sdata->u.sta.mesh_id_len) 236 if (sdata->u.mesh.mesh_id_len)
224 memcpy(pos, sdata->u.sta.mesh_id, sdata->u.sta.mesh_id_len); 237 memcpy(pos, sdata->u.mesh.mesh_id, sdata->u.mesh.mesh_id_len);
225 238
226 pos = skb_put(skb, 21); 239 pos = skb_put(skb, 21);
227 *pos++ = WLAN_EID_MESH_CONFIG; 240 *pos++ = WLAN_EID_MESH_CONFIG;
@@ -230,15 +243,15 @@ void mesh_mgmt_ies_add(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata)
230 *pos++ = 1; 243 *pos++ = 1;
231 244
232 /* Active path selection protocol ID */ 245 /* Active path selection protocol ID */
233 memcpy(pos, sdata->u.sta.mesh_pp_id, 4); 246 memcpy(pos, sdata->u.mesh.mesh_pp_id, 4);
234 pos += 4; 247 pos += 4;
235 248
236 /* Active path selection metric ID */ 249 /* Active path selection metric ID */
237 memcpy(pos, sdata->u.sta.mesh_pm_id, 4); 250 memcpy(pos, sdata->u.mesh.mesh_pm_id, 4);
238 pos += 4; 251 pos += 4;
239 252
240 /* Congestion control mode identifier */ 253 /* Congestion control mode identifier */
241 memcpy(pos, sdata->u.sta.mesh_cc_id, 4); 254 memcpy(pos, sdata->u.mesh.mesh_cc_id, 4);
242 pos += 4; 255 pos += 4;
243 256
244 /* Channel precedence: 257 /* Channel precedence:
@@ -248,8 +261,8 @@ void mesh_mgmt_ies_add(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata)
248 pos += 4; 261 pos += 4;
249 262
250 /* Mesh capability */ 263 /* Mesh capability */
251 sdata->u.sta.accepting_plinks = mesh_plink_availables(sdata); 264 sdata->u.mesh.accepting_plinks = mesh_plink_availables(sdata);
252 *pos++ = sdata->u.sta.accepting_plinks ? ACCEPT_PLINKS : 0x00; 265 *pos++ = sdata->u.mesh.accepting_plinks ? ACCEPT_PLINKS : 0x00;
253 *pos++ = 0x00; 266 *pos++ = 0x00;
254 267
255 return; 268 return;
@@ -337,10 +350,10 @@ static void ieee80211_mesh_path_timer(unsigned long data)
337{ 350{
338 struct ieee80211_sub_if_data *sdata = 351 struct ieee80211_sub_if_data *sdata =
339 (struct ieee80211_sub_if_data *) data; 352 (struct ieee80211_sub_if_data *) data;
340 struct ieee80211_if_sta *ifsta = &sdata->u.sta; 353 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
341 struct ieee80211_local *local = wdev_priv(&sdata->wdev); 354 struct ieee80211_local *local = wdev_priv(&sdata->wdev);
342 355
343 queue_work(local->hw.workqueue, &ifsta->work); 356 queue_work(local->hw.workqueue, &ifmsh->work);
344} 357}
345 358
346struct mesh_table *mesh_table_grow(struct mesh_table *tbl) 359struct mesh_table *mesh_table_grow(struct mesh_table *tbl)
@@ -392,50 +405,255 @@ int ieee80211_new_mesh_header(struct ieee80211s_hdr *meshhdr,
392 struct ieee80211_sub_if_data *sdata) 405 struct ieee80211_sub_if_data *sdata)
393{ 406{
394 meshhdr->flags = 0; 407 meshhdr->flags = 0;
395 meshhdr->ttl = sdata->u.sta.mshcfg.dot11MeshTTL; 408 meshhdr->ttl = sdata->u.mesh.mshcfg.dot11MeshTTL;
396 put_unaligned(cpu_to_le32(sdata->u.sta.mesh_seqnum), &meshhdr->seqnum); 409 put_unaligned(cpu_to_le32(sdata->u.mesh.mesh_seqnum), &meshhdr->seqnum);
397 sdata->u.sta.mesh_seqnum++; 410 sdata->u.mesh.mesh_seqnum++;
398 411
399 return 6; 412 return 6;
400} 413}
401 414
415static void ieee80211_mesh_housekeeping(struct ieee80211_sub_if_data *sdata,
416 struct ieee80211_if_mesh *ifmsh)
417{
418 bool free_plinks;
419
420#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
421 printk(KERN_DEBUG "%s: running mesh housekeeping\n",
422 sdata->dev->name);
423#endif
424
425 ieee80211_sta_expire(sdata, IEEE80211_MESH_PEER_INACTIVITY_LIMIT);
426 mesh_path_expire(sdata);
427
428 free_plinks = mesh_plink_availables(sdata);
429 if (free_plinks != sdata->u.mesh.accepting_plinks)
430 ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON);
431
432 ifmsh->housekeeping = false;
433 mod_timer(&ifmsh->housekeeping_timer,
434 round_jiffies(jiffies + IEEE80211_MESH_HOUSEKEEPING_INTERVAL));
435}
436
437
438void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata)
439{
440 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
441 struct ieee80211_local *local = sdata->local;
442
443 ifmsh->housekeeping = true;
444 queue_work(local->hw.workqueue, &ifmsh->work);
445 ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON);
446}
447
448void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata)
449{
450 del_timer_sync(&sdata->u.mesh.housekeeping_timer);
451 /*
452 * When we get here, the interface is marked down.
453 * Call synchronize_rcu() to wait for the RX path
454 * should it be using the interface and enqueuing
455 * frames at this very time on another CPU.
456 */
457 synchronize_rcu();
458 skb_queue_purge(&sdata->u.mesh.skb_queue);
459}
460
461static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata,
462 u16 stype,
463 struct ieee80211_mgmt *mgmt,
464 size_t len,
465 struct ieee80211_rx_status *rx_status)
466{
467 struct ieee80211_local *local= sdata->local;
468 struct ieee802_11_elems elems;
469 struct ieee80211_channel *channel;
470 u64 supp_rates = 0;
471 size_t baselen;
472 int freq;
473 enum ieee80211_band band = rx_status->band;
474
475 /* ignore ProbeResp to foreign address */
476 if (stype == IEEE80211_STYPE_PROBE_RESP &&
477 compare_ether_addr(mgmt->da, sdata->dev->dev_addr))
478 return;
479
480 baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt;
481 if (baselen > len)
482 return;
483
484 ieee802_11_parse_elems(mgmt->u.probe_resp.variable, len - baselen,
485 &elems);
486
487 if (elems.ds_params && elems.ds_params_len == 1)
488 freq = ieee80211_channel_to_frequency(elems.ds_params[0]);
489 else
490 freq = rx_status->freq;
491
492 channel = ieee80211_get_channel(local->hw.wiphy, freq);
493
494 if (!channel || channel->flags & IEEE80211_CHAN_DISABLED)
495 return;
496
497 if (elems.mesh_id && elems.mesh_config &&
498 mesh_matches_local(&elems, sdata)) {
499 supp_rates = ieee80211_sta_get_rates(local, &elems, band);
500
501 mesh_neighbour_update(mgmt->sa, supp_rates, sdata,
502 mesh_peer_accepts_plinks(&elems));
503 }
504}
505
506static void ieee80211_mesh_rx_mgmt_action(struct ieee80211_sub_if_data *sdata,
507 struct ieee80211_mgmt *mgmt,
508 size_t len,
509 struct ieee80211_rx_status *rx_status)
510{
511 switch (mgmt->u.action.category) {
512 case PLINK_CATEGORY:
513 mesh_rx_plink_frame(sdata, mgmt, len, rx_status);
514 break;
515 case MESH_PATH_SEL_CATEGORY:
516 mesh_rx_path_sel_frame(sdata, mgmt, len);
517 break;
518 }
519}
520
521static void ieee80211_mesh_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
522 struct sk_buff *skb)
523{
524 struct ieee80211_rx_status *rx_status;
525 struct ieee80211_if_mesh *ifmsh;
526 struct ieee80211_mgmt *mgmt;
527 u16 stype;
528
529 ifmsh = &sdata->u.mesh;
530
531 rx_status = (struct ieee80211_rx_status *) skb->cb;
532 mgmt = (struct ieee80211_mgmt *) skb->data;
533 stype = le16_to_cpu(mgmt->frame_control) & IEEE80211_FCTL_STYPE;
534
535 switch (stype) {
536 case IEEE80211_STYPE_PROBE_RESP:
537 case IEEE80211_STYPE_BEACON:
538 ieee80211_mesh_rx_bcn_presp(sdata, stype, mgmt, skb->len,
539 rx_status);
540 break;
541 case IEEE80211_STYPE_ACTION:
542 ieee80211_mesh_rx_mgmt_action(sdata, mgmt, skb->len, rx_status);
543 break;
544 }
545
546 kfree_skb(skb);
547}
548
549static void ieee80211_mesh_work(struct work_struct *work)
550{
551 struct ieee80211_sub_if_data *sdata =
552 container_of(work, struct ieee80211_sub_if_data, u.mesh.work);
553 struct ieee80211_local *local = sdata->local;
554 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
555 struct sk_buff *skb;
556
557 if (!netif_running(sdata->dev))
558 return;
559
560 if (local->sta_sw_scanning || local->sta_hw_scanning)
561 return;
562
563 while ((skb = skb_dequeue(&ifmsh->skb_queue)))
564 ieee80211_mesh_rx_queued_mgmt(sdata, skb);
565
566 if (ifmsh->preq_queue_len &&
567 time_after(jiffies,
568 ifmsh->last_preq + msecs_to_jiffies(ifmsh->mshcfg.dot11MeshHWMPpreqMinInterval)))
569 mesh_path_start_discovery(sdata);
570
571 if (ifmsh->housekeeping)
572 ieee80211_mesh_housekeeping(sdata, ifmsh);
573}
574
575void ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local)
576{
577 struct ieee80211_sub_if_data *sdata;
578
579 rcu_read_lock();
580 list_for_each_entry_rcu(sdata, &local->interfaces, list)
581 if (ieee80211_vif_is_mesh(&sdata->vif))
582 queue_work(local->hw.workqueue, &sdata->u.mesh.work);
583 rcu_read_unlock();
584}
585
402void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata) 586void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata)
403{ 587{
404 struct ieee80211_if_sta *ifsta = &sdata->u.sta; 588 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
405 589
406 ifsta->mshcfg.dot11MeshRetryTimeout = MESH_RET_T; 590 INIT_WORK(&ifmsh->work, ieee80211_mesh_work);
407 ifsta->mshcfg.dot11MeshConfirmTimeout = MESH_CONF_T; 591 setup_timer(&ifmsh->housekeeping_timer,
408 ifsta->mshcfg.dot11MeshHoldingTimeout = MESH_HOLD_T; 592 ieee80211_mesh_housekeeping_timer,
409 ifsta->mshcfg.dot11MeshMaxRetries = MESH_MAX_RETR; 593 (unsigned long) sdata);
410 ifsta->mshcfg.dot11MeshTTL = MESH_TTL; 594 skb_queue_head_init(&sdata->u.mesh.skb_queue);
411 ifsta->mshcfg.auto_open_plinks = true; 595
412 ifsta->mshcfg.dot11MeshMaxPeerLinks = 596 ifmsh->mshcfg.dot11MeshRetryTimeout = MESH_RET_T;
597 ifmsh->mshcfg.dot11MeshConfirmTimeout = MESH_CONF_T;
598 ifmsh->mshcfg.dot11MeshHoldingTimeout = MESH_HOLD_T;
599 ifmsh->mshcfg.dot11MeshMaxRetries = MESH_MAX_RETR;
600 ifmsh->mshcfg.dot11MeshTTL = MESH_TTL;
601 ifmsh->mshcfg.auto_open_plinks = true;
602 ifmsh->mshcfg.dot11MeshMaxPeerLinks =
413 MESH_MAX_ESTAB_PLINKS; 603 MESH_MAX_ESTAB_PLINKS;
414 ifsta->mshcfg.dot11MeshHWMPactivePathTimeout = 604 ifmsh->mshcfg.dot11MeshHWMPactivePathTimeout =
415 MESH_PATH_TIMEOUT; 605 MESH_PATH_TIMEOUT;
416 ifsta->mshcfg.dot11MeshHWMPpreqMinInterval = 606 ifmsh->mshcfg.dot11MeshHWMPpreqMinInterval =
417 MESH_PREQ_MIN_INT; 607 MESH_PREQ_MIN_INT;
418 ifsta->mshcfg.dot11MeshHWMPnetDiameterTraversalTime = 608 ifmsh->mshcfg.dot11MeshHWMPnetDiameterTraversalTime =
419 MESH_DIAM_TRAVERSAL_TIME; 609 MESH_DIAM_TRAVERSAL_TIME;
420 ifsta->mshcfg.dot11MeshHWMPmaxPREQretries = 610 ifmsh->mshcfg.dot11MeshHWMPmaxPREQretries =
421 MESH_MAX_PREQ_RETRIES; 611 MESH_MAX_PREQ_RETRIES;
422 ifsta->mshcfg.path_refresh_time = 612 ifmsh->mshcfg.path_refresh_time =
423 MESH_PATH_REFRESH_TIME; 613 MESH_PATH_REFRESH_TIME;
424 ifsta->mshcfg.min_discovery_timeout = 614 ifmsh->mshcfg.min_discovery_timeout =
425 MESH_MIN_DISCOVERY_TIMEOUT; 615 MESH_MIN_DISCOVERY_TIMEOUT;
426 ifsta->accepting_plinks = true; 616 ifmsh->accepting_plinks = true;
427 ifsta->preq_id = 0; 617 ifmsh->preq_id = 0;
428 ifsta->dsn = 0; 618 ifmsh->dsn = 0;
429 atomic_set(&ifsta->mpaths, 0); 619 atomic_set(&ifmsh->mpaths, 0);
430 mesh_rmc_init(sdata); 620 mesh_rmc_init(sdata);
431 ifsta->last_preq = jiffies; 621 ifmsh->last_preq = jiffies;
432 /* Allocate all mesh structures when creating the first mesh interface. */ 622 /* Allocate all mesh structures when creating the first mesh interface. */
433 if (!mesh_allocated) 623 if (!mesh_allocated)
434 ieee80211s_init(); 624 ieee80211s_init();
435 mesh_ids_set_default(ifsta); 625 mesh_ids_set_default(ifmsh);
436 setup_timer(&ifsta->mesh_path_timer, 626 setup_timer(&ifmsh->mesh_path_timer,
437 ieee80211_mesh_path_timer, 627 ieee80211_mesh_path_timer,
438 (unsigned long) sdata); 628 (unsigned long) sdata);
439 INIT_LIST_HEAD(&ifsta->preq_queue.list); 629 INIT_LIST_HEAD(&ifmsh->preq_queue.list);
440 spin_lock_init(&ifsta->mesh_preq_queue_lock); 630 spin_lock_init(&ifmsh->mesh_preq_queue_lock);
631}
632
633ieee80211_rx_result
634ieee80211_mesh_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb,
635 struct ieee80211_rx_status *rx_status)
636{
637 struct ieee80211_local *local = sdata->local;
638 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
639 struct ieee80211_mgmt *mgmt;
640 u16 fc;
641
642 if (skb->len < 24)
643 return RX_DROP_MONITOR;
644
645 mgmt = (struct ieee80211_mgmt *) skb->data;
646 fc = le16_to_cpu(mgmt->frame_control);
647
648 switch (fc & IEEE80211_FCTL_STYPE) {
649 case IEEE80211_STYPE_PROBE_RESP:
650 case IEEE80211_STYPE_BEACON:
651 case IEEE80211_STYPE_ACTION:
652 memcpy(skb->cb, rx_status, sizeof(*rx_status));
653 skb_queue_tail(&ifmsh->skb_queue, skb);
654 queue_work(local->hw.workqueue, &ifmsh->work);
655 return RX_QUEUED;
656 }
657
658 return RX_CONTINUE;
441} 659}
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h
index 84ff5d828fdb..8ee414a0447c 100644
--- a/net/mac80211/mesh.h
+++ b/net/mac80211/mesh.h
@@ -206,7 +206,7 @@ int mesh_rmc_check(u8 *addr, struct ieee80211s_hdr *mesh_hdr,
206 struct ieee80211_sub_if_data *sdata); 206 struct ieee80211_sub_if_data *sdata);
207bool mesh_matches_local(struct ieee802_11_elems *ie, 207bool mesh_matches_local(struct ieee802_11_elems *ie,
208 struct ieee80211_sub_if_data *sdata); 208 struct ieee80211_sub_if_data *sdata);
209void mesh_ids_set_default(struct ieee80211_if_sta *sta); 209void mesh_ids_set_default(struct ieee80211_if_mesh *mesh);
210void mesh_mgmt_ies_add(struct sk_buff *skb, 210void mesh_mgmt_ies_add(struct sk_buff *skb,
211 struct ieee80211_sub_if_data *sdata); 211 struct ieee80211_sub_if_data *sdata);
212void mesh_rmc_free(struct ieee80211_sub_if_data *sdata); 212void mesh_rmc_free(struct ieee80211_sub_if_data *sdata);
@@ -214,6 +214,11 @@ int mesh_rmc_init(struct ieee80211_sub_if_data *sdata);
214void ieee80211s_init(void); 214void ieee80211s_init(void);
215void ieee80211s_stop(void); 215void ieee80211s_stop(void);
216void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata); 216void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata);
217ieee80211_rx_result
218ieee80211_mesh_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb,
219 struct ieee80211_rx_status *rx_status);
220void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata);
221void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata);
217 222
218/* Mesh paths */ 223/* Mesh paths */
219int mesh_nexthop_lookup(struct sk_buff *skb, 224int mesh_nexthop_lookup(struct sk_buff *skb,
@@ -269,8 +274,8 @@ extern int mesh_allocated;
269 274
270static inline int mesh_plink_free_count(struct ieee80211_sub_if_data *sdata) 275static inline int mesh_plink_free_count(struct ieee80211_sub_if_data *sdata)
271{ 276{
272 return sdata->u.sta.mshcfg.dot11MeshMaxPeerLinks - 277 return sdata->u.mesh.mshcfg.dot11MeshMaxPeerLinks -
273 atomic_read(&sdata->u.sta.mshstats.estab_plinks); 278 atomic_read(&sdata->u.mesh.mshstats.estab_plinks);
274} 279}
275 280
276static inline bool mesh_plink_availables(struct ieee80211_sub_if_data *sdata) 281static inline bool mesh_plink_availables(struct ieee80211_sub_if_data *sdata)
@@ -288,8 +293,12 @@ static inline void mesh_path_activate(struct mesh_path *mpath)
288 for (i = 0; i <= x->hash_mask; i++) \ 293 for (i = 0; i <= x->hash_mask; i++) \
289 hlist_for_each_entry_rcu(node, p, &x->hash_buckets[i], list) 294 hlist_for_each_entry_rcu(node, p, &x->hash_buckets[i], list)
290 295
296void ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local);
297
291#else 298#else
292#define mesh_allocated 0 299#define mesh_allocated 0
300static inline void
301ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local) {}
293#endif 302#endif
294 303
295#endif /* IEEE80211S_H */ 304#endif /* IEEE80211S_H */
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c
index 210d6b852406..1fad792ad258 100644
--- a/net/mac80211/mesh_hwmp.c
+++ b/net/mac80211/mesh_hwmp.c
@@ -64,14 +64,14 @@ static inline u32 u32_field_get(u8 *preq_elem, int offset, bool ae)
64#define DSN_LT(x, y) ((long) (x) - (long) (y) < 0) 64#define DSN_LT(x, y) ((long) (x) - (long) (y) < 0)
65 65
66#define net_traversal_jiffies(s) \ 66#define net_traversal_jiffies(s) \
67 msecs_to_jiffies(s->u.sta.mshcfg.dot11MeshHWMPnetDiameterTraversalTime) 67 msecs_to_jiffies(s->u.mesh.mshcfg.dot11MeshHWMPnetDiameterTraversalTime)
68#define default_lifetime(s) \ 68#define default_lifetime(s) \
69 MSEC_TO_TU(s->u.sta.mshcfg.dot11MeshHWMPactivePathTimeout) 69 MSEC_TO_TU(s->u.mesh.mshcfg.dot11MeshHWMPactivePathTimeout)
70#define min_preq_int_jiff(s) \ 70#define min_preq_int_jiff(s) \
71 (msecs_to_jiffies(s->u.sta.mshcfg.dot11MeshHWMPpreqMinInterval)) 71 (msecs_to_jiffies(s->u.mesh.mshcfg.dot11MeshHWMPpreqMinInterval))
72#define max_preq_retries(s) (s->u.sta.mshcfg.dot11MeshHWMPmaxPREQretries) 72#define max_preq_retries(s) (s->u.mesh.mshcfg.dot11MeshHWMPmaxPREQretries)
73#define disc_timeout_jiff(s) \ 73#define disc_timeout_jiff(s) \
74 msecs_to_jiffies(sdata->u.sta.mshcfg.min_discovery_timeout) 74 msecs_to_jiffies(sdata->u.mesh.mshcfg.min_discovery_timeout)
75 75
76enum mpath_frame_type { 76enum mpath_frame_type {
77 MPATH_PREQ = 0, 77 MPATH_PREQ = 0,
@@ -395,7 +395,7 @@ static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata,
395static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata, 395static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata,
396 struct ieee80211_mgmt *mgmt, 396 struct ieee80211_mgmt *mgmt,
397 u8 *preq_elem, u32 metric) { 397 u8 *preq_elem, u32 metric) {
398 struct ieee80211_if_sta *ifsta = &sdata->u.sta; 398 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
399 struct mesh_path *mpath; 399 struct mesh_path *mpath;
400 u8 *dst_addr, *orig_addr; 400 u8 *dst_addr, *orig_addr;
401 u8 dst_flags, ttl; 401 u8 dst_flags, ttl;
@@ -414,11 +414,11 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata,
414 forward = false; 414 forward = false;
415 reply = true; 415 reply = true;
416 metric = 0; 416 metric = 0;
417 if (time_after(jiffies, ifsta->last_dsn_update + 417 if (time_after(jiffies, ifmsh->last_dsn_update +
418 net_traversal_jiffies(sdata)) || 418 net_traversal_jiffies(sdata)) ||
419 time_before(jiffies, ifsta->last_dsn_update)) { 419 time_before(jiffies, ifmsh->last_dsn_update)) {
420 dst_dsn = ++ifsta->dsn; 420 dst_dsn = ++ifmsh->dsn;
421 ifsta->last_dsn_update = jiffies; 421 ifmsh->last_dsn_update = jiffies;
422 } 422 }
423 } else { 423 } else {
424 rcu_read_lock(); 424 rcu_read_lock();
@@ -444,7 +444,7 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata,
444 444
445 if (reply) { 445 if (reply) {
446 lifetime = PREQ_IE_LIFETIME(preq_elem); 446 lifetime = PREQ_IE_LIFETIME(preq_elem);
447 ttl = ifsta->mshcfg.dot11MeshTTL; 447 ttl = ifmsh->mshcfg.dot11MeshTTL;
448 if (ttl != 0) 448 if (ttl != 0)
449 mesh_path_sel_frame_tx(MPATH_PREP, 0, dst_addr, 449 mesh_path_sel_frame_tx(MPATH_PREP, 0, dst_addr,
450 cpu_to_le32(dst_dsn), 0, orig_addr, 450 cpu_to_le32(dst_dsn), 0, orig_addr,
@@ -452,7 +452,7 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata,
452 cpu_to_le32(lifetime), cpu_to_le32(metric), 452 cpu_to_le32(lifetime), cpu_to_le32(metric),
453 0, sdata); 453 0, sdata);
454 else 454 else
455 ifsta->mshstats.dropped_frames_ttl++; 455 ifmsh->mshstats.dropped_frames_ttl++;
456 } 456 }
457 457
458 if (forward) { 458 if (forward) {
@@ -462,7 +462,7 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata,
462 ttl = PREQ_IE_TTL(preq_elem); 462 ttl = PREQ_IE_TTL(preq_elem);
463 lifetime = PREQ_IE_LIFETIME(preq_elem); 463 lifetime = PREQ_IE_LIFETIME(preq_elem);
464 if (ttl <= 1) { 464 if (ttl <= 1) {
465 ifsta->mshstats.dropped_frames_ttl++; 465 ifmsh->mshstats.dropped_frames_ttl++;
466 return; 466 return;
467 } 467 }
468 --ttl; 468 --ttl;
@@ -475,7 +475,7 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata,
475 hopcount, ttl, cpu_to_le32(lifetime), 475 hopcount, ttl, cpu_to_le32(lifetime),
476 cpu_to_le32(metric), cpu_to_le32(preq_id), 476 cpu_to_le32(metric), cpu_to_le32(preq_id),
477 sdata); 477 sdata);
478 ifsta->mshstats.fwded_frames++; 478 ifmsh->mshstats.fwded_frames++;
479 } 479 }
480} 480}
481 481
@@ -503,7 +503,7 @@ static void hwmp_prep_frame_process(struct ieee80211_sub_if_data *sdata,
503 503
504 ttl = PREP_IE_TTL(prep_elem); 504 ttl = PREP_IE_TTL(prep_elem);
505 if (ttl <= 1) { 505 if (ttl <= 1) {
506 sdata->u.sta.mshstats.dropped_frames_ttl++; 506 sdata->u.mesh.mshstats.dropped_frames_ttl++;
507 return; 507 return;
508 } 508 }
509 509
@@ -533,12 +533,12 @@ static void hwmp_prep_frame_process(struct ieee80211_sub_if_data *sdata,
533 cpu_to_le32(lifetime), cpu_to_le32(metric), 533 cpu_to_le32(lifetime), cpu_to_le32(metric),
534 0, sdata); 534 0, sdata);
535 rcu_read_unlock(); 535 rcu_read_unlock();
536 sdata->u.sta.mshstats.fwded_frames++; 536 sdata->u.mesh.mshstats.fwded_frames++;
537 return; 537 return;
538 538
539fail: 539fail:
540 rcu_read_unlock(); 540 rcu_read_unlock();
541 sdata->u.sta.mshstats.dropped_frames_no_route++; 541 sdata->u.mesh.mshstats.dropped_frames_no_route++;
542 return; 542 return;
543} 543}
544 544
@@ -631,7 +631,7 @@ void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata,
631static void mesh_queue_preq(struct mesh_path *mpath, u8 flags) 631static void mesh_queue_preq(struct mesh_path *mpath, u8 flags)
632{ 632{
633 struct ieee80211_sub_if_data *sdata = mpath->sdata; 633 struct ieee80211_sub_if_data *sdata = mpath->sdata;
634 struct ieee80211_if_sta *ifsta = &sdata->u.sta; 634 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
635 struct mesh_preq_queue *preq_node; 635 struct mesh_preq_queue *preq_node;
636 636
637 preq_node = kmalloc(sizeof(struct mesh_preq_queue), GFP_KERNEL); 637 preq_node = kmalloc(sizeof(struct mesh_preq_queue), GFP_KERNEL);
@@ -640,9 +640,9 @@ static void mesh_queue_preq(struct mesh_path *mpath, u8 flags)
640 return; 640 return;
641 } 641 }
642 642
643 spin_lock(&ifsta->mesh_preq_queue_lock); 643 spin_lock(&ifmsh->mesh_preq_queue_lock);
644 if (ifsta->preq_queue_len == MAX_PREQ_QUEUE_LEN) { 644 if (ifmsh->preq_queue_len == MAX_PREQ_QUEUE_LEN) {
645 spin_unlock(&ifsta->mesh_preq_queue_lock); 645 spin_unlock(&ifmsh->mesh_preq_queue_lock);
646 kfree(preq_node); 646 kfree(preq_node);
647 if (printk_ratelimit()) 647 if (printk_ratelimit())
648 printk(KERN_DEBUG "Mesh HWMP: PREQ node queue full\n"); 648 printk(KERN_DEBUG "Mesh HWMP: PREQ node queue full\n");
@@ -652,21 +652,21 @@ static void mesh_queue_preq(struct mesh_path *mpath, u8 flags)
652 memcpy(preq_node->dst, mpath->dst, ETH_ALEN); 652 memcpy(preq_node->dst, mpath->dst, ETH_ALEN);
653 preq_node->flags = flags; 653 preq_node->flags = flags;
654 654
655 list_add_tail(&preq_node->list, &ifsta->preq_queue.list); 655 list_add_tail(&preq_node->list, &ifmsh->preq_queue.list);
656 ++ifsta->preq_queue_len; 656 ++ifmsh->preq_queue_len;
657 spin_unlock(&ifsta->mesh_preq_queue_lock); 657 spin_unlock(&ifmsh->mesh_preq_queue_lock);
658 658
659 if (time_after(jiffies, ifsta->last_preq + min_preq_int_jiff(sdata))) 659 if (time_after(jiffies, ifmsh->last_preq + min_preq_int_jiff(sdata)))
660 queue_work(sdata->local->hw.workqueue, &ifsta->work); 660 queue_work(sdata->local->hw.workqueue, &ifmsh->work);
661 661
662 else if (time_before(jiffies, ifsta->last_preq)) { 662 else if (time_before(jiffies, ifmsh->last_preq)) {
663 /* avoid long wait if did not send preqs for a long time 663 /* avoid long wait if did not send preqs for a long time
664 * and jiffies wrapped around 664 * and jiffies wrapped around
665 */ 665 */
666 ifsta->last_preq = jiffies - min_preq_int_jiff(sdata) - 1; 666 ifmsh->last_preq = jiffies - min_preq_int_jiff(sdata) - 1;
667 queue_work(sdata->local->hw.workqueue, &ifsta->work); 667 queue_work(sdata->local->hw.workqueue, &ifmsh->work);
668 } else 668 } else
669 mod_timer(&ifsta->mesh_path_timer, ifsta->last_preq + 669 mod_timer(&ifmsh->mesh_path_timer, ifmsh->last_preq +
670 min_preq_int_jiff(sdata)); 670 min_preq_int_jiff(sdata));
671} 671}
672 672
@@ -677,25 +677,25 @@ static void mesh_queue_preq(struct mesh_path *mpath, u8 flags)
677 */ 677 */
678void mesh_path_start_discovery(struct ieee80211_sub_if_data *sdata) 678void mesh_path_start_discovery(struct ieee80211_sub_if_data *sdata)
679{ 679{
680 struct ieee80211_if_sta *ifsta = &sdata->u.sta; 680 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
681 struct mesh_preq_queue *preq_node; 681 struct mesh_preq_queue *preq_node;
682 struct mesh_path *mpath; 682 struct mesh_path *mpath;
683 u8 ttl, dst_flags; 683 u8 ttl, dst_flags;
684 u32 lifetime; 684 u32 lifetime;
685 685
686 spin_lock(&ifsta->mesh_preq_queue_lock); 686 spin_lock(&ifmsh->mesh_preq_queue_lock);
687 if (!ifsta->preq_queue_len || 687 if (!ifmsh->preq_queue_len ||
688 time_before(jiffies, ifsta->last_preq + 688 time_before(jiffies, ifmsh->last_preq +
689 min_preq_int_jiff(sdata))) { 689 min_preq_int_jiff(sdata))) {
690 spin_unlock(&ifsta->mesh_preq_queue_lock); 690 spin_unlock(&ifmsh->mesh_preq_queue_lock);
691 return; 691 return;
692 } 692 }
693 693
694 preq_node = list_first_entry(&ifsta->preq_queue.list, 694 preq_node = list_first_entry(&ifmsh->preq_queue.list,
695 struct mesh_preq_queue, list); 695 struct mesh_preq_queue, list);
696 list_del(&preq_node->list); 696 list_del(&preq_node->list);
697 --ifsta->preq_queue_len; 697 --ifmsh->preq_queue_len;
698 spin_unlock(&ifsta->mesh_preq_queue_lock); 698 spin_unlock(&ifmsh->mesh_preq_queue_lock);
699 699
700 rcu_read_lock(); 700 rcu_read_lock();
701 mpath = mesh_path_lookup(preq_node->dst, sdata); 701 mpath = mesh_path_lookup(preq_node->dst, sdata);
@@ -720,18 +720,18 @@ void mesh_path_start_discovery(struct ieee80211_sub_if_data *sdata)
720 goto enddiscovery; 720 goto enddiscovery;
721 } 721 }
722 722
723 ifsta->last_preq = jiffies; 723 ifmsh->last_preq = jiffies;
724 724
725 if (time_after(jiffies, ifsta->last_dsn_update + 725 if (time_after(jiffies, ifmsh->last_dsn_update +
726 net_traversal_jiffies(sdata)) || 726 net_traversal_jiffies(sdata)) ||
727 time_before(jiffies, ifsta->last_dsn_update)) { 727 time_before(jiffies, ifmsh->last_dsn_update)) {
728 ++ifsta->dsn; 728 ++ifmsh->dsn;
729 sdata->u.sta.last_dsn_update = jiffies; 729 sdata->u.mesh.last_dsn_update = jiffies;
730 } 730 }
731 lifetime = default_lifetime(sdata); 731 lifetime = default_lifetime(sdata);
732 ttl = sdata->u.sta.mshcfg.dot11MeshTTL; 732 ttl = sdata->u.mesh.mshcfg.dot11MeshTTL;
733 if (ttl == 0) { 733 if (ttl == 0) {
734 sdata->u.sta.mshstats.dropped_frames_ttl++; 734 sdata->u.mesh.mshstats.dropped_frames_ttl++;
735 spin_unlock_bh(&mpath->state_lock); 735 spin_unlock_bh(&mpath->state_lock);
736 goto enddiscovery; 736 goto enddiscovery;
737 } 737 }
@@ -743,10 +743,10 @@ void mesh_path_start_discovery(struct ieee80211_sub_if_data *sdata)
743 743
744 spin_unlock_bh(&mpath->state_lock); 744 spin_unlock_bh(&mpath->state_lock);
745 mesh_path_sel_frame_tx(MPATH_PREQ, 0, sdata->dev->dev_addr, 745 mesh_path_sel_frame_tx(MPATH_PREQ, 0, sdata->dev->dev_addr,
746 cpu_to_le32(ifsta->dsn), dst_flags, mpath->dst, 746 cpu_to_le32(ifmsh->dsn), dst_flags, mpath->dst,
747 cpu_to_le32(mpath->dsn), sdata->dev->broadcast, 0, 747 cpu_to_le32(mpath->dsn), sdata->dev->broadcast, 0,
748 ttl, cpu_to_le32(lifetime), 0, 748 ttl, cpu_to_le32(lifetime), 0,
749 cpu_to_le32(ifsta->preq_id++), sdata); 749 cpu_to_le32(ifmsh->preq_id++), sdata);
750 mod_timer(&mpath->timer, jiffies + mpath->discovery_timeout); 750 mod_timer(&mpath->timer, jiffies + mpath->discovery_timeout);
751 751
752enddiscovery: 752enddiscovery:
@@ -783,7 +783,7 @@ int mesh_nexthop_lookup(struct sk_buff *skb,
783 mpath = mesh_path_lookup(dst_addr, sdata); 783 mpath = mesh_path_lookup(dst_addr, sdata);
784 if (!mpath) { 784 if (!mpath) {
785 dev_kfree_skb(skb); 785 dev_kfree_skb(skb);
786 sdata->u.sta.mshstats.dropped_frames_no_route++; 786 sdata->u.mesh.mshstats.dropped_frames_no_route++;
787 err = -ENOSPC; 787 err = -ENOSPC;
788 goto endlookup; 788 goto endlookup;
789 } 789 }
@@ -791,7 +791,7 @@ int mesh_nexthop_lookup(struct sk_buff *skb,
791 791
792 if (mpath->flags & MESH_PATH_ACTIVE) { 792 if (mpath->flags & MESH_PATH_ACTIVE) {
793 if (time_after(jiffies, mpath->exp_time - 793 if (time_after(jiffies, mpath->exp_time -
794 msecs_to_jiffies(sdata->u.sta.mshcfg.path_refresh_time)) 794 msecs_to_jiffies(sdata->u.mesh.mshcfg.path_refresh_time))
795 && !memcmp(sdata->dev->dev_addr, hdr->addr4, 795 && !memcmp(sdata->dev->dev_addr, hdr->addr4,
796 ETH_ALEN) 796 ETH_ALEN)
797 && !(mpath->flags & MESH_PATH_RESOLVING) 797 && !(mpath->flags & MESH_PATH_RESOLVING)
diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c
index 0a60f55f32ab..e4fa2905fadc 100644
--- a/net/mac80211/mesh_pathtbl.c
+++ b/net/mac80211/mesh_pathtbl.c
@@ -153,7 +153,7 @@ int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata)
153 if (is_multicast_ether_addr(dst)) 153 if (is_multicast_ether_addr(dst))
154 return -ENOTSUPP; 154 return -ENOTSUPP;
155 155
156 if (atomic_add_unless(&sdata->u.sta.mpaths, 1, MESH_MAX_MPATHS) == 0) 156 if (atomic_add_unless(&sdata->u.mesh.mpaths, 1, MESH_MAX_MPATHS) == 0)
157 return -ENOSPC; 157 return -ENOSPC;
158 158
159 err = -ENOMEM; 159 err = -ENOMEM;
@@ -221,7 +221,7 @@ err_exists:
221err_node_alloc: 221err_node_alloc:
222 kfree(new_mpath); 222 kfree(new_mpath);
223err_path_alloc: 223err_path_alloc:
224 atomic_dec(&sdata->u.sta.mpaths); 224 atomic_dec(&sdata->u.mesh.mpaths);
225 return err; 225 return err;
226} 226}
227 227
@@ -306,7 +306,7 @@ static void mesh_path_node_reclaim(struct rcu_head *rp)
306 struct ieee80211_sub_if_data *sdata = node->mpath->sdata; 306 struct ieee80211_sub_if_data *sdata = node->mpath->sdata;
307 307
308 del_timer_sync(&node->mpath->timer); 308 del_timer_sync(&node->mpath->timer);
309 atomic_dec(&sdata->u.sta.mpaths); 309 atomic_dec(&sdata->u.mesh.mpaths);
310 kfree(node->mpath); 310 kfree(node->mpath);
311 kfree(node); 311 kfree(node);
312} 312}
@@ -401,7 +401,7 @@ void mesh_path_discard_frame(struct sk_buff *skb,
401 } 401 }
402 402
403 kfree_skb(skb); 403 kfree_skb(skb);
404 sdata->u.sta.mshstats.dropped_frames_no_route++; 404 sdata->u.mesh.mshstats.dropped_frames_no_route++;
405} 405}
406 406
407/** 407/**
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c
index 7356462dee96..990a4b7f6bcc 100644
--- a/net/mac80211/mesh_plink.c
+++ b/net/mac80211/mesh_plink.c
@@ -36,11 +36,11 @@
36#define MESH_SECURITY_AUTHENTICATION_IMPOSSIBLE 9 36#define MESH_SECURITY_AUTHENTICATION_IMPOSSIBLE 9
37#define MESH_SECURITY_FAILED_VERIFICATION 10 37#define MESH_SECURITY_FAILED_VERIFICATION 10
38 38
39#define dot11MeshMaxRetries(s) (s->u.sta.mshcfg.dot11MeshMaxRetries) 39#define dot11MeshMaxRetries(s) (s->u.mesh.mshcfg.dot11MeshMaxRetries)
40#define dot11MeshRetryTimeout(s) (s->u.sta.mshcfg.dot11MeshRetryTimeout) 40#define dot11MeshRetryTimeout(s) (s->u.mesh.mshcfg.dot11MeshRetryTimeout)
41#define dot11MeshConfirmTimeout(s) (s->u.sta.mshcfg.dot11MeshConfirmTimeout) 41#define dot11MeshConfirmTimeout(s) (s->u.mesh.mshcfg.dot11MeshConfirmTimeout)
42#define dot11MeshHoldingTimeout(s) (s->u.sta.mshcfg.dot11MeshHoldingTimeout) 42#define dot11MeshHoldingTimeout(s) (s->u.mesh.mshcfg.dot11MeshHoldingTimeout)
43#define dot11MeshMaxPeerLinks(s) (s->u.sta.mshcfg.dot11MeshMaxPeerLinks) 43#define dot11MeshMaxPeerLinks(s) (s->u.mesh.mshcfg.dot11MeshMaxPeerLinks)
44 44
45enum plink_frame_type { 45enum plink_frame_type {
46 PLINK_OPEN = 0, 46 PLINK_OPEN = 0,
@@ -63,14 +63,14 @@ enum plink_event {
63static inline 63static inline
64void mesh_plink_inc_estab_count(struct ieee80211_sub_if_data *sdata) 64void mesh_plink_inc_estab_count(struct ieee80211_sub_if_data *sdata)
65{ 65{
66 atomic_inc(&sdata->u.sta.mshstats.estab_plinks); 66 atomic_inc(&sdata->u.mesh.mshstats.estab_plinks);
67 mesh_accept_plinks_update(sdata); 67 mesh_accept_plinks_update(sdata);
68} 68}
69 69
70static inline 70static inline
71void mesh_plink_dec_estab_count(struct ieee80211_sub_if_data *sdata) 71void mesh_plink_dec_estab_count(struct ieee80211_sub_if_data *sdata)
72{ 72{
73 atomic_dec(&sdata->u.sta.mshstats.estab_plinks); 73 atomic_dec(&sdata->u.mesh.mshstats.estab_plinks);
74 mesh_accept_plinks_update(sdata); 74 mesh_accept_plinks_update(sdata);
75} 75}
76 76
@@ -245,8 +245,8 @@ void mesh_neighbour_update(u8 *hw_addr, u64 rates, struct ieee80211_sub_if_data
245 sta->last_rx = jiffies; 245 sta->last_rx = jiffies;
246 sta->supp_rates[local->hw.conf.channel->band] = rates; 246 sta->supp_rates[local->hw.conf.channel->band] = rates;
247 if (peer_accepting_plinks && sta->plink_state == PLINK_LISTEN && 247 if (peer_accepting_plinks && sta->plink_state == PLINK_LISTEN &&
248 sdata->u.sta.accepting_plinks && 248 sdata->u.mesh.accepting_plinks &&
249 sdata->u.sta.mshcfg.auto_open_plinks) 249 sdata->u.mesh.mshcfg.auto_open_plinks)
250 mesh_plink_open(sta); 250 mesh_plink_open(sta);
251 251
252 rcu_read_unlock(); 252 rcu_read_unlock();
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index ef73f8953724..9e20a0c20a46 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -22,11 +22,11 @@
22#include <linux/rtnetlink.h> 22#include <linux/rtnetlink.h>
23#include <net/iw_handler.h> 23#include <net/iw_handler.h>
24#include <net/mac80211.h> 24#include <net/mac80211.h>
25#include <asm/unaligned.h>
25 26
26#include "ieee80211_i.h" 27#include "ieee80211_i.h"
27#include "rate.h" 28#include "rate.h"
28#include "led.h" 29#include "led.h"
29#include "mesh.h"
30 30
31#define IEEE80211_ASSOC_SCANS_MAX_TRIES 2 31#define IEEE80211_ASSOC_SCANS_MAX_TRIES 2
32#define IEEE80211_AUTH_TIMEOUT (HZ / 5) 32#define IEEE80211_AUTH_TIMEOUT (HZ / 5)
@@ -34,7 +34,6 @@
34#define IEEE80211_ASSOC_TIMEOUT (HZ / 5) 34#define IEEE80211_ASSOC_TIMEOUT (HZ / 5)
35#define IEEE80211_ASSOC_MAX_TRIES 3 35#define IEEE80211_ASSOC_MAX_TRIES 3
36#define IEEE80211_MONITORING_INTERVAL (2 * HZ) 36#define IEEE80211_MONITORING_INTERVAL (2 * HZ)
37#define IEEE80211_MESH_HOUSEKEEPING_INTERVAL (60 * HZ)
38#define IEEE80211_PROBE_INTERVAL (60 * HZ) 37#define IEEE80211_PROBE_INTERVAL (60 * HZ)
39#define IEEE80211_RETRY_AUTH_INTERVAL (1 * HZ) 38#define IEEE80211_RETRY_AUTH_INTERVAL (1 * HZ)
40#define IEEE80211_SCAN_INTERVAL (2 * HZ) 39#define IEEE80211_SCAN_INTERVAL (2 * HZ)
@@ -43,7 +42,6 @@
43 42
44#define IEEE80211_IBSS_MERGE_INTERVAL (30 * HZ) 43#define IEEE80211_IBSS_MERGE_INTERVAL (30 * HZ)
45#define IEEE80211_IBSS_INACTIVITY_LIMIT (60 * HZ) 44#define IEEE80211_IBSS_INACTIVITY_LIMIT (60 * HZ)
46#define IEEE80211_MESH_PEER_INACTIVITY_LIMIT (1800 * HZ)
47 45
48#define IEEE80211_IBSS_MAX_STA_ENTRIES 128 46#define IEEE80211_IBSS_MAX_STA_ENTRIES 128
49 47
@@ -1508,14 +1506,6 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
1508 if (!channel || channel->flags & IEEE80211_CHAN_DISABLED) 1506 if (!channel || channel->flags & IEEE80211_CHAN_DISABLED)
1509 return; 1507 return;
1510 1508
1511 if (ieee80211_vif_is_mesh(&sdata->vif) && elems->mesh_id &&
1512 elems->mesh_config && mesh_matches_local(elems, sdata)) {
1513 supp_rates = ieee80211_sta_get_rates(local, elems, band);
1514
1515 mesh_neighbour_update(mgmt->sa, supp_rates, sdata,
1516 mesh_peer_accepts_plinks(elems));
1517 }
1518
1519 if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS && elems->supp_rates && 1509 if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS && elems->supp_rates &&
1520 memcmp(mgmt->bssid, sdata->u.sta.bssid, ETH_ALEN) == 0) { 1510 memcmp(mgmt->bssid, sdata->u.sta.bssid, ETH_ALEN) == 0) {
1521 supp_rates = ieee80211_sta_get_rates(local, elems, band); 1511 supp_rates = ieee80211_sta_get_rates(local, elems, band);
@@ -1785,26 +1775,6 @@ static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata,
1785 ieee80211_tx_skb(sdata, skb, 0); 1775 ieee80211_tx_skb(sdata, skb, 0);
1786} 1776}
1787 1777
1788static void ieee80211_rx_mgmt_action(struct ieee80211_sub_if_data *sdata,
1789 struct ieee80211_if_sta *ifsta,
1790 struct ieee80211_mgmt *mgmt,
1791 size_t len,
1792 struct ieee80211_rx_status *rx_status)
1793{
1794 /* currently we only handle mesh interface action frames here */
1795 if (!ieee80211_vif_is_mesh(&sdata->vif))
1796 return;
1797
1798 switch (mgmt->u.action.category) {
1799 case PLINK_CATEGORY:
1800 mesh_rx_plink_frame(sdata, mgmt, len, rx_status);
1801 break;
1802 case MESH_PATH_SEL_CATEGORY:
1803 mesh_rx_path_sel_frame(sdata, mgmt, len);
1804 break;
1805 }
1806}
1807
1808void ieee80211_sta_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, 1778void ieee80211_sta_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb,
1809 struct ieee80211_rx_status *rx_status) 1779 struct ieee80211_rx_status *rx_status)
1810{ 1780{
@@ -1825,7 +1795,6 @@ void ieee80211_sta_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *
1825 case IEEE80211_STYPE_PROBE_REQ: 1795 case IEEE80211_STYPE_PROBE_REQ:
1826 case IEEE80211_STYPE_PROBE_RESP: 1796 case IEEE80211_STYPE_PROBE_RESP:
1827 case IEEE80211_STYPE_BEACON: 1797 case IEEE80211_STYPE_BEACON:
1828 case IEEE80211_STYPE_ACTION:
1829 memcpy(skb->cb, rx_status, sizeof(*rx_status)); 1798 memcpy(skb->cb, rx_status, sizeof(*rx_status));
1830 case IEEE80211_STYPE_AUTH: 1799 case IEEE80211_STYPE_AUTH:
1831 case IEEE80211_STYPE_ASSOC_RESP: 1800 case IEEE80211_STYPE_ASSOC_RESP:
@@ -1881,9 +1850,6 @@ static void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
1881 case IEEE80211_STYPE_DISASSOC: 1850 case IEEE80211_STYPE_DISASSOC:
1882 ieee80211_rx_mgmt_disassoc(sdata, ifsta, mgmt, skb->len); 1851 ieee80211_rx_mgmt_disassoc(sdata, ifsta, mgmt, skb->len);
1883 break; 1852 break;
1884 case IEEE80211_STYPE_ACTION:
1885 ieee80211_rx_mgmt_action(sdata, ifsta, mgmt, skb->len, rx_status);
1886 break;
1887 } 1853 }
1888 1854
1889 kfree_skb(skb); 1855 kfree_skb(skb);
@@ -1928,35 +1894,6 @@ static void ieee80211_sta_merge_ibss(struct ieee80211_sub_if_data *sdata,
1928} 1894}
1929 1895
1930 1896
1931#ifdef CONFIG_MAC80211_MESH
1932static void ieee80211_mesh_housekeeping(struct ieee80211_sub_if_data *sdata,
1933 struct ieee80211_if_sta *ifsta)
1934{
1935 bool free_plinks;
1936
1937 ieee80211_sta_expire(sdata, IEEE80211_MESH_PEER_INACTIVITY_LIMIT);
1938 mesh_path_expire(sdata);
1939
1940 free_plinks = mesh_plink_availables(sdata);
1941 if (free_plinks != sdata->u.sta.accepting_plinks)
1942 ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON);
1943
1944 mod_timer(&ifsta->timer, jiffies +
1945 IEEE80211_MESH_HOUSEKEEPING_INTERVAL);
1946}
1947
1948
1949void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata)
1950{
1951 struct ieee80211_if_sta *ifsta;
1952 ifsta = &sdata->u.sta;
1953 ifsta->state = IEEE80211_STA_MLME_MESH_UP;
1954 ieee80211_sta_timer((unsigned long)sdata);
1955 ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON);
1956}
1957#endif
1958
1959
1960void ieee80211_sta_timer(unsigned long data) 1897void ieee80211_sta_timer(unsigned long data)
1961{ 1898{
1962 struct ieee80211_sub_if_data *sdata = 1899 struct ieee80211_sub_if_data *sdata =
@@ -2524,21 +2461,13 @@ void ieee80211_sta_work(struct work_struct *work)
2524 return; 2461 return;
2525 2462
2526 if (WARN_ON(sdata->vif.type != IEEE80211_IF_TYPE_STA && 2463 if (WARN_ON(sdata->vif.type != IEEE80211_IF_TYPE_STA &&
2527 sdata->vif.type != IEEE80211_IF_TYPE_IBSS && 2464 sdata->vif.type != IEEE80211_IF_TYPE_IBSS))
2528 sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT))
2529 return; 2465 return;
2530 ifsta = &sdata->u.sta; 2466 ifsta = &sdata->u.sta;
2531 2467
2532 while ((skb = skb_dequeue(&ifsta->skb_queue))) 2468 while ((skb = skb_dequeue(&ifsta->skb_queue)))
2533 ieee80211_sta_rx_queued_mgmt(sdata, skb); 2469 ieee80211_sta_rx_queued_mgmt(sdata, skb);
2534 2470
2535#ifdef CONFIG_MAC80211_MESH
2536 if (ifsta->preq_queue_len &&
2537 time_after(jiffies,
2538 ifsta->last_preq + msecs_to_jiffies(ifsta->mshcfg.dot11MeshHWMPpreqMinInterval)))
2539 mesh_path_start_discovery(sdata);
2540#endif
2541
2542 if (ifsta->state != IEEE80211_STA_MLME_DIRECT_PROBE && 2471 if (ifsta->state != IEEE80211_STA_MLME_DIRECT_PROBE &&
2543 ifsta->state != IEEE80211_STA_MLME_AUTHENTICATE && 2472 ifsta->state != IEEE80211_STA_MLME_AUTHENTICATE &&
2544 ifsta->state != IEEE80211_STA_MLME_ASSOCIATE && 2473 ifsta->state != IEEE80211_STA_MLME_ASSOCIATE &&
@@ -2575,11 +2504,6 @@ void ieee80211_sta_work(struct work_struct *work)
2575 case IEEE80211_STA_MLME_IBSS_JOINED: 2504 case IEEE80211_STA_MLME_IBSS_JOINED:
2576 ieee80211_sta_merge_ibss(sdata, ifsta); 2505 ieee80211_sta_merge_ibss(sdata, ifsta);
2577 break; 2506 break;
2578#ifdef CONFIG_MAC80211_MESH
2579 case IEEE80211_STA_MLME_MESH_UP:
2580 ieee80211_mesh_housekeeping(sdata, ifsta);
2581 break;
2582#endif
2583 default: 2507 default:
2584 WARN_ON(1); 2508 WARN_ON(1);
2585 break; 2509 break;
@@ -2596,8 +2520,7 @@ void ieee80211_sta_work(struct work_struct *work)
2596 2520
2597static void ieee80211_restart_sta_timer(struct ieee80211_sub_if_data *sdata) 2521static void ieee80211_restart_sta_timer(struct ieee80211_sub_if_data *sdata)
2598{ 2522{
2599 if (sdata->vif.type == IEEE80211_IF_TYPE_STA || 2523 if (sdata->vif.type == IEEE80211_IF_TYPE_STA)
2600 ieee80211_vif_is_mesh(&sdata->vif))
2601 queue_work(sdata->local->hw.workqueue, 2524 queue_work(sdata->local->hw.workqueue,
2602 &sdata->u.sta.work); 2525 &sdata->u.sta.work);
2603} 2526}
diff --git a/net/mac80211/rc80211_pid_algo.c b/net/mac80211/rc80211_pid_algo.c
index a914ba73ccf5..21e1942ea975 100644
--- a/net/mac80211/rc80211_pid_algo.c
+++ b/net/mac80211/rc80211_pid_algo.c
@@ -148,9 +148,7 @@ static void rate_control_pid_sample(struct rc_pid_info *pinfo,
148 struct ieee80211_local *local, 148 struct ieee80211_local *local,
149 struct sta_info *sta) 149 struct sta_info *sta)
150{ 150{
151#ifdef CONFIG_MAC80211_MESH
152 struct ieee80211_sub_if_data *sdata = sta->sdata; 151 struct ieee80211_sub_if_data *sdata = sta->sdata;
153#endif
154 struct rc_pid_sta_info *spinfo = sta->rate_ctrl_priv; 152 struct rc_pid_sta_info *spinfo = sta->rate_ctrl_priv;
155 struct rc_pid_rateinfo *rinfo = pinfo->rinfo; 153 struct rc_pid_rateinfo *rinfo = pinfo->rinfo;
156 struct ieee80211_supported_band *sband; 154 struct ieee80211_supported_band *sband;
@@ -181,11 +179,8 @@ static void rate_control_pid_sample(struct rc_pid_info *pinfo,
181 pf = spinfo->last_pf; 179 pf = spinfo->last_pf;
182 else { 180 else {
183 pf = spinfo->tx_num_failed * 100 / spinfo->tx_num_xmit; 181 pf = spinfo->tx_num_failed * 100 / spinfo->tx_num_xmit;
184#ifdef CONFIG_MAC80211_MESH 182 if (ieee80211_vif_is_mesh(&sdata->vif) && pf == 100)
185 if (pf == 100 &&
186 sdata->vif.type == IEEE80211_IF_TYPE_MESH_POINT)
187 mesh_plink_broken(sta); 183 mesh_plink_broken(sta);
188#endif
189 pf <<= RC_PID_ARITH_SHIFT; 184 pf <<= RC_PID_ARITH_SHIFT;
190 sta->fail_avg = ((pf + (spinfo->last_pf << 3)) / 9) 185 sta->fail_avg = ((pf + (spinfo->last_pf << 3)) / 9)
191 >> RC_PID_ARITH_SHIFT; 186 >> RC_PID_ARITH_SHIFT;
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index d0803797902b..208563a27bc4 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -1404,7 +1404,7 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
1404 1404
1405 if (rx->flags & IEEE80211_RX_RA_MATCH) { 1405 if (rx->flags & IEEE80211_RX_RA_MATCH) {
1406 if (!mesh_hdr->ttl) 1406 if (!mesh_hdr->ttl)
1407 IEEE80211_IFSTA_MESH_CTR_INC(&rx->sdata->u.sta, 1407 IEEE80211_IFSTA_MESH_CTR_INC(&rx->sdata->u.mesh,
1408 dropped_frames_ttl); 1408 dropped_frames_ttl);
1409 else { 1409 else {
1410 struct ieee80211_hdr *fwd_hdr; 1410 struct ieee80211_hdr *fwd_hdr;
@@ -1591,9 +1591,11 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx)
1591 if (!(rx->flags & IEEE80211_RX_RA_MATCH)) 1591 if (!(rx->flags & IEEE80211_RX_RA_MATCH))
1592 return RX_DROP_MONITOR; 1592 return RX_DROP_MONITOR;
1593 1593
1594 if (ieee80211_vif_is_mesh(&sdata->vif))
1595 return ieee80211_mesh_rx_mgmt(sdata, rx->skb, rx->status);
1596
1594 if (sdata->vif.type != IEEE80211_IF_TYPE_STA && 1597 if (sdata->vif.type != IEEE80211_IF_TYPE_STA &&
1595 sdata->vif.type != IEEE80211_IF_TYPE_IBSS && 1598 sdata->vif.type != IEEE80211_IF_TYPE_IBSS)
1596 sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT)
1597 return RX_DROP_MONITOR; 1599 return RX_DROP_MONITOR;
1598 1600
1599 if (sdata->flags & IEEE80211_SDATA_USERSPACE_MLME) 1601 if (sdata->flags & IEEE80211_SDATA_USERSPACE_MLME)
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index f8b296bed0b9..f4399e9ac928 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -476,6 +476,7 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw)
476 476
477 done: 477 done:
478 ieee80211_mlme_notify_scan_completed(local); 478 ieee80211_mlme_notify_scan_completed(local);
479 ieee80211_mesh_notify_scan_completed(local);
479} 480}
480EXPORT_SYMBOL(ieee80211_scan_completed); 481EXPORT_SYMBOL(ieee80211_scan_completed);
481 482
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index c413d4836afe..1059b17c83b0 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -1330,7 +1330,7 @@ int ieee80211_master_start_xmit(struct sk_buff *skb,
1330 if (mesh_nexthop_lookup(skb, osdata)) 1330 if (mesh_nexthop_lookup(skb, osdata))
1331 return 0; 1331 return 0;
1332 if (memcmp(odev->dev_addr, hdr->addr4, ETH_ALEN) != 0) 1332 if (memcmp(odev->dev_addr, hdr->addr4, ETH_ALEN) != 0)
1333 IEEE80211_IFSTA_MESH_CTR_INC(&osdata->u.sta, 1333 IEEE80211_IFSTA_MESH_CTR_INC(&osdata->u.mesh,
1334 fwded_frames); 1334 fwded_frames);
1335 } 1335 }
1336 } 1336 }
@@ -1483,9 +1483,9 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb,
1483 memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN); 1483 memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN);
1484 memcpy(hdr.addr3, skb->data, ETH_ALEN); 1484 memcpy(hdr.addr3, skb->data, ETH_ALEN);
1485 memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN); 1485 memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN);
1486 if (!sdata->u.sta.mshcfg.dot11MeshTTL) { 1486 if (!sdata->u.mesh.mshcfg.dot11MeshTTL) {
1487 /* Do not send frames with mesh_ttl == 0 */ 1487 /* Do not send frames with mesh_ttl == 0 */
1488 sdata->u.sta.mshstats.dropped_frames_ttl++; 1488 sdata->u.mesh.mshstats.dropped_frames_ttl++;
1489 ret = 0; 1489 ret = 0;
1490 goto fail; 1490 goto fail;
1491 } 1491 }
@@ -1815,10 +1815,8 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw,
1815 struct rate_selection rsel; 1815 struct rate_selection rsel;
1816 struct beacon_data *beacon; 1816 struct beacon_data *beacon;
1817 struct ieee80211_supported_band *sband; 1817 struct ieee80211_supported_band *sband;
1818 struct ieee80211_mgmt *mgmt;
1819 int *num_beacons; 1818 int *num_beacons;
1820 enum ieee80211_band band = local->hw.conf.channel->band; 1819 enum ieee80211_band band = local->hw.conf.channel->band;
1821 u8 *pos;
1822 1820
1823 sband = local->hw.wiphy->bands[band]; 1821 sband = local->hw.wiphy->bands[band];
1824 1822
@@ -1885,7 +1883,11 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw,
1885 IEEE80211_STYPE_BEACON); 1883 IEEE80211_STYPE_BEACON);
1886 1884
1887 num_beacons = &ifsta->num_beacons; 1885 num_beacons = &ifsta->num_beacons;
1886#ifdef CONFIG_MAC80211_MESH
1888 } else if (ieee80211_vif_is_mesh(&sdata->vif)) { 1887 } else if (ieee80211_vif_is_mesh(&sdata->vif)) {
1888 struct ieee80211_mgmt *mgmt;
1889 u8 *pos;
1890
1889 /* headroom, head length, tail length and maximum TIM length */ 1891 /* headroom, head length, tail length and maximum TIM length */
1890 skb = dev_alloc_skb(local->tx_headroom + 400); 1892 skb = dev_alloc_skb(local->tx_headroom + 400);
1891 if (!skb) 1893 if (!skb)
@@ -1910,7 +1912,8 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw,
1910 1912
1911 mesh_mgmt_ies_add(skb, sdata); 1913 mesh_mgmt_ies_add(skb, sdata);
1912 1914
1913 num_beacons = &sdata->u.sta.num_beacons; 1915 num_beacons = &sdata->u.mesh.num_beacons;
1916#endif
1914 } else { 1917 } else {
1915 WARN_ON(1); 1918 WARN_ON(1);
1916 goto out; 1919 goto out;